<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Windows &#8211; Blog of Kliment Andreev &#8211; A place so I won&#039;t forget things</title>
	<atom:link href="https://blog.andreev.it/category/windows/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.andreev.it</link>
	<description></description>
	<lastBuildDate>Wed, 04 Nov 2020 20:00:09 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>AWS, OKTA: Single sign-on in AWS Console using OKTA and on-prem Active Directory (AD)</title>
		<link>https://blog.andreev.it/2020/02/aws-okta-single-sign-on-in-aws-console-using-okta-and-on-prem-active-directory-ad/</link>
					<comments>https://blog.andreev.it/2020/02/aws-okta-single-sign-on-in-aws-console-using-okta-and-on-prem-active-directory-ad/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sun, 16 Feb 2020 20:33:31 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[AD]]></category>
		<category><![CDATA[OKTA]]></category>
		<category><![CDATA[SSO]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=6483</guid>

					<description><![CDATA[AWS Console has its own authentication/authorization directory using IAM users, roles and policies. On&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>AWS Console has its own authentication/authorization directory using IAM users, roles and policies. On top of that, they also offer multi-factor authentication, so your logins are much more secure. But, I wanted to see how I can use Okta for SSO between my AD domain at home and AWS. The setup is very simple as you can see from this diagram.<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-01.png"><img fetchpriority="high" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-01.png" alt="" width="1778" height="1174" class="aligncenter size-full wp-image-6486" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-01.png 1778w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-300x198.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-1024x676.png 1024w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-768x507.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-1536x1014.png 1536w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-1170x773.png 1170w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-780x516.png 780w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-585x386.png 585w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-01-263x175.png 263w" sizes="(max-width: 1778px) 100vw, 1778px" /></a><br />
On the left side, AWS is missing &#8211; but you get the point. In my case, I&#8217;ll have two AD groups, <strong>AWS Full Admin</strong> and <strong>AWS Read Only</strong>. I also have two AD users, <strong>admin.user</strong> and <strong>ro.user</strong>. If you haven&#8217;t integrated your AD with Okta it&#8217;s time to do so. </p>
<h1>Okta</h1>
<p>Go to the Okta dashboard and from the menu go to <strong>Directory | Directory Integrations</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-02.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-02.png" alt="" width="742" height="500" class="aligncenter size-full wp-image-6490" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-02.png 742w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-02-300x202.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-02-585x394.png 585w" sizes="(max-width: 742px) 100vw, 742px" /></a><br />
Click on <strong>Add Active Directory</strong> and proceed so you can download an agent that you have to install on a member server with at least 8GB RAM. You can also install it on a domain controller, which I did in my lab, but I guess it&#8217;s not recommended. You&#8217;ll see this page telling you that Okta is waiting for your AD to connect.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-03.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-03.png" alt="" width="955" height="501" class="aligncenter size-full wp-image-6491" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-03.png 955w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-03-300x157.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-03-768x403.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-03-585x307.png 585w" sizes="(max-width: 955px) 100vw, 955px" /></a><br />
Go ahead and install the agent. You&#8217;ll be prompted to specify the domain name (<strong>andreev.local</strong> in my case), create a service account <strong>OktaService </strong>or choose an existing one, choose a proxy to connect to Okta servers over HTTPS (if needed) and finally you have to specify your Okta domain, e.g. the prefix for your Okta landing page, https://company.Okta.com. You have to type -company-.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-04.png" alt="" width="481" height="339" class="aligncenter size-full wp-image-6492" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-04.png 481w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-04-300x211.png 300w" sizes="(max-width: 481px) 100vw, 481px" /></a><br />
Once the service starts and authenticates with your Okta admin account to the Okta servers, your dashboard page will change asking you to specify what OUs in your AD you want to sync. Choose the OUs and choose your Okta username format.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-05.png" alt="" width="915" height="856" class="aligncenter size-full wp-image-6493" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-05.png 915w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-05-300x281.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-05-768x718.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-05-585x547.png 585w" sizes="(max-width: 915px) 100vw, 915px" /></a><br />
In my case I&#8217;ll use UPN which is <strong>username@andreev.local</strong>, but you can choose e-mail if your have a valid e-mail specified for the users, e.g. <strong>username@google.com</strong> or the SAM account which is your login that you use for AD, e.g. <strong>username</strong>. See below.<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-06.png" alt="" width="395" height="327" class="aligncenter size-full wp-image-6497" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-06.png 395w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-06-300x248.png 300w" sizes="(max-width: 395px) 100vw, 395px" /></a><br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-07.png" alt="" width="393" height="172" class="aligncenter size-full wp-image-6498" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-07.png 393w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-07-300x131.png 300w" sizes="(max-width: 393px) 100vw, 393px" /></a><br />
Click <strong>Next </strong>and unless you have some non-standard AD attributes that you want to map, it&#8217;s safe to proceed with the defaults. Under the settings for the AD in Okta, you can choose the scheduled interval for the AD sync. By default, this sync is disabled. To test the integration, go to the settings page of your AD in Okta, choose <strong>Test Delegated Authentication</strong> (bottom right) and enter the username and password for an AD account that you know it&#8217;s synced with Okta.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-08.png" alt="" width="1077" height="687" class="aligncenter size-full wp-image-6500" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-08.png 1077w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-08-300x191.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-08-1024x653.png 1024w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-08-768x490.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-08-585x373.png 585w" sizes="(max-width: 1077px) 100vw, 1077px" /></a><br />
You can also test the integration if you go to https://-company-.okta.com and log in with a synced AD user. </p>
<h2>Okta app for AWS</h2>
<p>Before we move to AWS part, click on <strong>Applications </strong>from the menu and click on <strong>Add Application</strong> menu. Type <strong>Amazon Web Services</strong> and select the app. Do not use AWS Console app, that&#8217;s a different one.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-09.png" alt="" width="764" height="353" class="aligncenter size-full wp-image-6503" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-09.png 764w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-09-300x139.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-09-585x270.png 585w" sizes="(max-width: 764px) 100vw, 764px" /></a><br />
Click <strong>Add </strong>and you can leave the settings under <strong>General Settings</strong> or change it to AWS Console. Click <strong>Next </strong>and on the next screen, use <strong>SAML 2.0</strong><br />
Click on the <strong>Identity Provider Metadata</strong> link and download the file. You&#8217;ll need this for later.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-10.png" alt="" width="680" height="313" class="aligncenter size-full wp-image-6505" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-10.png 680w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-10-300x138.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-10-585x269.png 585w" sizes="(max-width: 680px) 100vw, 680px" /></a><br />
Click <strong>Done </strong>and once this part is completed, we can go to AWS Console and configure AWS IAM and then come back to Okta. </p>
<h1>AWS Console</h1>
<p>Log to the AWS Console with an account with sufficient rights to create IAM polices, roles and users. Go to <strong>IAM </strong>and then <strong>Identity Providers</strong> on the left side. Click <strong>Create Provider</strong> and choose <strong>SAML </strong>for <strong>Provider Type</strong>, type a description (e.g. <strong>OKTA</strong>) and choose the <strong>metadata </strong>file that you&#8217;ve just downloaded.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-11.png" alt="" width="563" height="255" class="aligncenter size-full wp-image-6506" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-11.png 563w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-11-300x136.png 300w" sizes="(max-width: 563px) 100vw, 563px" /></a><br />
Click on<strong> Next Step</strong> and then <strong>Create</strong>. Click on the entry that you just created and make a note of the ARN. You&#8217;ll need this later.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-12.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-12.png" alt="" width="657" height="239" class="aligncenter size-full wp-image-6507" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-12.png 657w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-12-300x109.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-12-585x213.png 585w" sizes="(max-width: 657px) 100vw, 657px" /></a></p>
<h2>IAM</h2>
<p>We&#8217;ll create two new roles based on existing AWS policies for full admin access and read only access. Go to <strong>IAM </strong>| <strong>Roles</strong> and click on <strong>Create Role</strong>. Click on <strong>SAML 2.0 federation</strong>, choose the <strong>SAML </strong>provider that we just created, select <strong>Allow programmatic and AWS Management Console</strong> access and click on <strong>Next: Permissions</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-13.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-13.png" alt="" width="1007" height="819" class="aligncenter size-full wp-image-6509" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-13.png 1007w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-13-300x244.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-13-768x625.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-13-585x476.png 585w" sizes="(max-width: 1007px) 100vw, 1007px" /></a><br />
You can create your own policy if you want by clicking on <strong>Create policy</strong> or choose an existing one like I did by filtering the <strong>Read Only</strong> policies. Click on <strong>Next: Tags</strong> after.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-14.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-14.png" alt="" width="1027" height="809" class="aligncenter size-full wp-image-6510" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-14.png 1027w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-14-300x236.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-14-1024x807.png 1024w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-14-768x605.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-14-585x461.png 585w" sizes="(max-width: 1027px) 100vw, 1027px" /></a><br />
You can tag your role and click <strong>Next: Review</strong> after&#8230;and finally you can create the role.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-16.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-16.png" alt="" width="1033" height="792" class="aligncenter size-full wp-image-6511" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-16.png 1033w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-16-300x230.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-16-1024x785.png 1024w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-16-768x589.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-16-585x449.png 585w" sizes="(max-width: 1033px) 100vw, 1033px" /></a><br />
Do the same again <strong>IAM | Roles | SAML</strong>, but this time create a full admin role named <strong>rolFullAdminAccess </strong>(filter the policies by <strong>Administrator</strong>).<br />
Let&#8217;s connect AWS and Okta now, but creating a user that will be able to list the roles. Go to <strong>IAM | User</strong> and click on <strong>Add user</strong>. Name your user and allow <strong>Programmatic access</strong> only.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-17.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-17.png" alt="" width="889" height="490" class="aligncenter size-full wp-image-6513" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-17.png 889w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-17-300x165.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-17-768x423.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-17-585x322.png 585w" sizes="(max-width: 889px) 100vw, 889px" /></a><br />
Click on <strong>Create policy</strong>. This will open a new window. Do not close the previous one.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-18.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-18.png" alt="" width="769" height="249" class="aligncenter size-full wp-image-6514" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-18.png 769w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-18-300x97.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-18-585x189.png 585w" sizes="(max-width: 769px) 100vw, 769px" /></a><br />
Click on the <strong>JSON </strong>tab and paste this policy. Then click <strong>Review policy</strong>.</p>
<pre class="brush: xml; title: ; notranslate">
{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: &#x5B;
        {
          &quot;Effect&quot;: &quot;Allow&quot;,
          &quot;Action&quot;: &#x5B;
              &quot;iam:ListRoles&quot;,
              &quot;iam:ListAccountAliases&quot;
          ],
          &quot;Resource&quot;: &quot;*&quot;
        }
    ]
}
</pre>
<p>Name your policy and click on <strong>Create policy</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-19.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-19.png" alt="" width="1214" height="592" class="aligncenter size-full wp-image-6517" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-19.png 1214w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-19-300x146.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-19-1024x499.png 1024w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-19-768x375.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-19-1170x571.png 1170w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-19-585x285.png 585w" sizes="(max-width: 1214px) 100vw, 1214px" /></a><br />
Go back to the previous tab and click on the refresh button, right off the <strong>Create policy</strong> button. Then filter the policy and assign it. Click <strong>Next: Tags</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-20.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-20.png" alt="" width="1004" height="241" class="aligncenter size-full wp-image-6518" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-20.png 1004w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-20-300x72.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-20-768x184.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-20-585x140.png 585w" sizes="(max-width: 1004px) 100vw, 1004px" /></a><br />
Proceed to create the user, but make sure you download the CSV file with the credentials for this user.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-21.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-21.png" alt="" width="1003" height="191" class="aligncenter size-full wp-image-6520" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-21.png 1003w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-21-300x57.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-21-768x146.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-21-585x111.png 585w" sizes="(max-width: 1003px) 100vw, 1003px" /></a></p>
<h1>Okta &#8211; app config</h1>
<p>Go back to Okta and click on the<strong> Sign On</strong> tab and then <strong>Edit</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-22.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-22.png" alt="" width="748" height="283" class="aligncenter size-full wp-image-6522" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-22.png 748w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-22-300x114.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-22-585x221.png 585w" sizes="(max-width: 748px) 100vw, 748px" /></a><br />
Scroll down a little bit and paste your ARN value (the one that you got from AWS earlier) under <strong>Identity Provider ARN (Required only for SAML SSO</strong>. It&#8217;s under <strong>IAM | Providers | -your-provider</strong> in AWS. Click <strong>Save</strong> after.<br />
Click on the <strong>Provisioning </strong>tab next to <strong>Sign On</strong> and click on <strong>Configure API Integration</strong>. Click the checkmark, then copy and paste the access key and the secret from the CSV file from AWS. Click Test API Credentials and if everything is OK, click on Save.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-24.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-24.png" alt="" width="803" height="411" class="aligncenter size-full wp-image-6524" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-24.png 803w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-24-300x154.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-24-768x393.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-24-585x299.png 585w" sizes="(max-width: 803px) 100vw, 803px" /></a><br />
Under <strong>Provisioning </strong>make sure that <strong>Create Users</strong> and <strong>Update User Attributes</strong> are enabled.<br />
Finally, go to the <strong>Assignments </strong>tab and select <strong>Groups</strong>. Then, click the green button <strong>Assign </strong>and choose <strong>Assign to Groups</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-26.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-26.png" alt="" width="598" height="399" class="aligncenter size-full wp-image-6527" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-26.png 598w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-26-300x200.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-26-585x390.png 585w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-26-263x175.png 263w" sizes="(max-width: 598px) 100vw, 598px" /></a><br />
You will see your groups here, select the first one and click the <strong>Assign </strong>button.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-27.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-27.png" alt="" width="630" height="608" class="aligncenter size-full wp-image-6528" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-27.png 630w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-27-300x290.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-27-585x565.png 585w" sizes="(max-width: 630px) 100vw, 630px" /></a><br />
You will see your roles there. Select the admin role and Save.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-28.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-28.png" alt="" width="616" height="581" class="aligncenter size-full wp-image-6529" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-28.png 616w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-28-300x283.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-28-585x552.png 585w" sizes="(max-width: 616px) 100vw, 616px" /></a><br />
Do the same for the other group and role and pretty much you are all set. Open a new browser and this time log as one of the users, in my case I am logging as admin.user to https://mycompany.okta.com.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-29.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-29.png" alt="" width="697" height="686" class="aligncenter size-full wp-image-6531" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-29.png 697w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-29-300x295.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-29-585x576.png 585w" sizes="(max-width: 697px) 100vw, 697px" /></a><br />
You&#8217;ll get a note that you have a new app assigned.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-30.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-30.png" alt="" width="764" height="365" class="aligncenter size-full wp-image-6532" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-30.png 764w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-30-300x143.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-30-585x279.png 585w" sizes="(max-width: 764px) 100vw, 764px" /></a><br />
If you click on the app icon, you&#8217;ll get logged in to the AWS console without any passwords.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-31.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-31.png" alt="" width="933" height="473" class="aligncenter size-full wp-image-6533" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-31.png 933w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-31-300x152.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-31-768x389.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-31-585x297.png 585w" sizes="(max-width: 933px) 100vw, 933px" /></a></p>
<h1>Multi-factor authentication</h1>
<p>While the above setup looks good, you still need MFA to make things even more secure. Go to the app settings in Okta and click on the Sign On tab then click Edit.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-32.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-32.png" alt="" width="736" height="256" class="aligncenter size-full wp-image-6535" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-32.png 736w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-32-300x104.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-32-585x203.png 585w" sizes="(max-width: 736px) 100vw, 736px" /></a><br />
Scroll all the way down and click on Add Rule.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-33.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-33.png" alt="" width="741" height="360" class="aligncenter size-full wp-image-6536" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-33.png 741w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-33-300x146.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-33-585x284.png 585w" sizes="(max-width: 741px) 100vw, 741px" /></a><br />
Name the rule however you want and scroll all the way down.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-34.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-34.png" alt="" width="806" height="206" class="aligncenter size-full wp-image-6537" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-34.png 806w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-34-300x77.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-34-768x196.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-34-585x150.png 585w" sizes="(max-width: 806px) 100vw, 806px" /></a><br />
Click on Prompt for fact and choose whatever you want from the settings.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-35.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-35.png" alt="" width="784" height="536" class="aligncenter size-full wp-image-6538" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-35.png 784w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-35-300x205.png 300w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-35-768x525.png 768w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-35-585x400.png 585w" sizes="(max-width: 784px) 100vw, 784px" /></a><br />
Once configured, when you log in to your Okta dashboard, you&#8217;ll get in without prompted for MFA, but when you click on the AWS Console app, you&#8217;ll get redirected to AWS to configure your MFA. You can use the Okta mobile app for MFA or Authy which I prefer. This is because we configured the MFA to occur on the AWS level, not on Okta level.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2020/02/P145-36.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2020/02/P145-36.png" alt="" width="511" height="628" class="aligncenter size-full wp-image-6540" srcset="https://blog.andreev.it/wp-content/uploads/2020/02/P145-36.png 511w, https://blog.andreev.it/wp-content/uploads/2020/02/P145-36-244x300.png 244w" sizes="(max-width: 511px) 100vw, 511px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2020/02/aws-okta-single-sign-on-in-aws-console-using-okta-and-on-prem-active-directory-ad/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWS, Windows: MS SQL 2017 with AlwaysOn (Named Instance, WSFC) on AWS</title>
		<link>https://blog.andreev.it/2019/07/windows-ms-sql-2017-with-alwayson-named-instance-wsfc-on-aws/</link>
					<comments>https://blog.andreev.it/2019/07/windows-ms-sql-2017-with-alwayson-named-instance-wsfc-on-aws/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Mon, 08 Jul 2019 20:16:10 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[AlwaysOn]]></category>
		<category><![CDATA[MS SQL]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=5313</guid>

					<description><![CDATA[In this article, I&#8217;ll explain how to install and configure two Windows 2019 servers&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this article, I&#8217;ll explain how to install and configure two Windows 2019 servers running MS SQL 2017 Enterprise with <a href="https://docs.microsoft.com/en-us/sql/database-engine/availability-groups/windows/overview-of-always-on-availability-groups-sql-server?view=sql-server-2017" rel="noopener noreferrer" target="_blank">AlwaysOn</a>. The servers will have local storage only but you&#8217;ll still have HA. There are several prerequisites that you need in order to test this scenario. </p>
<ul>
&#8211; Functional AD and rights to create objects in AD<br />
&#8211; Unrestricted traffic access between the SQL nodes and AD (you can probably restrict the ports, but do your research)<br />
&#8211; Two AD accounts (an user account and a SQL service account)<br />
&#8211; Two extra IPs assigned to each SQL node<br />
&#8211; Proper DNS resolution in AWS and time synced between the nodes and DCs</ul>
</ul>
<h1>Domain controllers and AD</h1>
<p>I have two DCs running in two zones in the same region. Make sure that you can ping/resolve the servers by using only the short DNS name. E.g. My first domain controller is dc01. When I do <strong>ping dc02</strong> from dc01, it resolves fine. If not, check the DNS settings. You should also check the advanced DNS settings. Make sure that your domain is on the top. In my case, I have the DNS settings of dc01 pointing to itself and dc02. Notice ad-domain.local on top of other suffixes. <strong>AD-DOMAIN.LOCAL</strong> is the name of my domain. If you have the DNS suffixes configured on the VPC level, you don&#8217;t have to make this change. The only thing important is that you have a proper DNS resolution.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-01.png" alt="" width="1167" height="490" class="aligncenter size-full wp-image-8540" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-01.png 1167w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-01-300x126.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-01-1024x430.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-01-768x322.png 768w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-01-585x246.png 585w" sizes="(max-width: 1167px) 100vw, 1167px" /></a><br />
Open up <strong>AD Users and Computers (dsa.msc)</strong> and create a single service account for the SQL servers. I&#8217;ll call it <strong>svc_sql</strong> and it should be a member of <strong>Domain Users</strong> only. The password should never expire. This account will run the SQL DB engine on SQL nodes.<br />
Then create an OU for the cluster object. In my case, I&#8217;ll create an OU called <strong>SQLCLUSTERS</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-02.png" alt="" width="362" height="278" class="aligncenter size-full wp-image-8541" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-02.png 362w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-02-300x230.png 300w" sizes="(max-width: 362px) 100vw, 362px" /></a><br />
Then create the name of your SQL cluster as a computer object and disable it.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-03.png" alt="" width="579" height="295" class="aligncenter size-full wp-image-8542" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-03.png 579w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-03-300x153.png 300w" sizes="(max-width: 579px) 100vw, 579px" /></a><br />
In <strong>AD Users and Computers</strong>, under the <strong>View </strong>menu, make sure that <strong>Advanced Features</strong> is enabled. Right-click the SQL cluster computer object and choose <strong>Properties</strong>, then click on <strong>Security </strong>tab and click <strong>Add</strong>. Type the name of the service account you just created and give it <strong>Full Control</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-04.png" alt="" width="460" height="528" class="aligncenter size-full wp-image-8543" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-04.png 460w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-04-261x300.png 261w" sizes="(max-width: 460px) 100vw, 460px" /></a><br />
We also need the cluster computer account to have rights to the OU. Right-click the OU that you just created, choose <strong>Properties </strong>and under the <strong>Security </strong>tab, click <strong>Advanced</strong>.<br />
You&#8217;ll see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-05.png" alt="" width="763" height="520" class="aligncenter size-full wp-image-8544" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-05.png 763w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-05-300x204.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-05-585x399.png 585w" sizes="(max-width: 763px) 100vw, 763px" /></a><br />
Click <strong>Add </strong>and in the new dialog that shows up, in the upper left corner, click the link <strong>Select a principal</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-06.png" alt="" width="588" height="347" class="aligncenter size-full wp-image-8545" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-06.png 588w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-06-300x177.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-06-585x345.png 585w" sizes="(max-width: 588px) 100vw, 588px" /></a><br />
By default, computer object are not going to show up, so click on <strong>Object Types</strong> button, then check <strong>Computer </strong>and click <strong>OK </strong>to go back to the screen above.<br />
Type the name of the SQL cluster and click on <strong>Check Names</strong> to verify it.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-07.png" alt="" width="457" height="250" class="aligncenter size-full wp-image-8546" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-07.png 457w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-07-300x164.png 300w" sizes="(max-width: 457px) 100vw, 457px" /></a><br />
Click OK when it reminds you that the object is disabled. In the <strong>Permission Entry</strong> dialog box, make sure that the Type is set to <strong>Allow</strong>, and the <strong>Applies to</strong> is set to <strong>This object and all descendant objects</strong>. Finally, under <strong>Permissions</strong>, click on the <strong>Create Computer objects</strong> check box. Click<strong> OK</strong> until you close all open dialogs.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-08.png" alt="" width="899" height="553" class="aligncenter size-full wp-image-8547" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-08.png 899w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-08-300x185.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-08-768x472.png 768w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-08-585x360.png 585w" sizes="(max-width: 899px) 100vw, 899px" /></a><br />
The AD part is now complete.</p>
<h1>WSFC (Windows Server Failover Cluster)</h1>
<p>Now, we have to create and configure the failover cluster. I have two SQL nodes, <strong>node01 </strong>and <strong>node02</strong>. We have to install WSFC on each node, but before doing that, let&#8217;s add extra two IPs per node. In AWS console, on each SQL instance, click on the network adapter, usually called <strong>eth0</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-09.png" alt="" width="1015" height="284" class="aligncenter size-full wp-image-8548" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-09.png 1015w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-09-300x84.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-09-768x215.png 768w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-09-585x164.png 585w" sizes="(max-width: 1015px) 100vw, 1015px" /></a><br />
Click on the <strong>Interface ID</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-10.png" alt="" width="443" height="155" class="aligncenter size-full wp-image-8549" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-10.png 443w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-10-300x105.png 300w" sizes="(max-width: 443px) 100vw, 443px" /></a><br />
Then from the <strong>Actions </strong>drop down, click on <strong>Manage IP Addresses</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-11.png" alt="" width="695" height="265" class="aligncenter size-full wp-image-8550" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-11.png 695w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-11-300x114.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-11-585x223.png 585w" sizes="(max-width: 695px) 100vw, 695px" /></a><br />
Add two extra IPs per instance. You can choose DHCP provided IPs or manual. I decided to go with manual assignment. Make sure the IPs are in the same subnet as the primary and they are not in use.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-12.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-12.png" alt="" width="618" height="253" class="aligncenter size-full wp-image-8551" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-12.png 618w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-12-300x123.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-12-585x239.png 585w" sizes="(max-width: 618px) 100vw, 618px" /></a><br />
For <strong>node01</strong>, I&#8217;ll use <strong>192.168.1.60</strong> and <strong>192.168.1.61</strong> and for <strong>node02 </strong>I&#8217;ll use <strong>192.168.2.60</strong> and <strong>192.168.2.61</strong>. <strong>node01 </strong>and <strong>dc01 </strong>are in a <strong>192.168.1.0/24</strong> subnet and <strong>node02 </strong>and <strong>dc02 </strong>are in <strong>192.168.2.0/24</strong> subnet. Now, log to both nodes with an admin account and add the SQL service account <strong>svc_sql</strong> as a local administrator. Then log off and log back to SQL nodes as <strong>svc_sql</strong> service account.<br />
On both nodes, install the WSFC (Windows Server Failover Cluster) from an elevated PowerShell prompt and reboot.</p>
<pre class="brush: powershell; title: ; notranslate">
Install-WindowsFeature -Name Failover-Clustering -IncludeManagementTools
</pre>
<p>Once the instances come back, log as <strong>svc_sql</strong> and create the cluster. Open up an elevated command or PowerShell prompt and type <strong>cluadmin.msc</strong> (do this on one node, not both). In the wizard dialog box, click <strong>Browse </strong>and type the name of the nodes.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-13.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-13.png" alt="" width="533" height="260" class="aligncenter size-full wp-image-8552" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-13.png 533w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-13-300x146.png 300w" sizes="(max-width: 533px) 100vw, 533px" /></a><br />
The cluster wizard will do some pre-checks and if everything looks good click <strong>Next</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-14.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-14.png" alt="" width="534" height="259" class="aligncenter size-full wp-image-8553" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-14.png 534w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-14-300x146.png 300w" sizes="(max-width: 534px) 100vw, 534px" /></a><br />
Do not skip this part. Make sure you validate the cluster and you run all tests. It takes about a minute or two.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-15.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-15.png" alt="" width="527" height="115" class="aligncenter size-full wp-image-8554" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-15.png 527w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-15-300x65.png 300w" sizes="(max-width: 527px) 100vw, 527px" /></a><br />
You&#8217;ll see some warnings about the network, but you can ignore them. <a href="https://blog.andreev.it/wp-content/uploads/2019/07/Failover-Cluster-Validation-Report_htm50.zip" rel="noopener noreferrer" target="_blank">This </a>is how my report looked like. You&#8217;ll be able to enter the name of the cluster if everything is OK. In my case, the cluster name is the disabled computer object <strong>SQLCLUSTER01 </strong>that we created earlier.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-16.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-16.png" alt="" width="531" height="371" class="aligncenter size-full wp-image-8555" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-16.png 531w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-16-300x210.png 300w" sizes="(max-width: 531px) 100vw, 531px" /></a><br />
Make sure you uncheck the storage setting. We are using local storage, so there is nothing to add to the cluster as a resource.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-17.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-17.png" alt="" width="533" height="339" class="aligncenter size-full wp-image-8556" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-17.png 533w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-17-300x191.png 300w" sizes="(max-width: 533px) 100vw, 533px" /></a><br />
After a minute, you should get a greeting that the cluster is OK.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-18.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-18.png" alt="" width="536" height="349" class="aligncenter size-full wp-image-8557" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-18.png 536w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-18-300x195.png 300w" sizes="(max-width: 536px) 100vw, 536px" /></a><br />
Back in the cluster manager, you&#8217;ll see this mess. Don&#8217;t worry.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-19.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-19.png" alt="" width="920" height="587" class="aligncenter size-full wp-image-8558" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-19.png 920w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-19-300x191.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-19-768x490.png 768w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-19-585x373.png 585w" sizes="(max-width: 920px) 100vw, 920px" /></a><br />
At the bottom of the cluster manager, right click the first node and choose <strong>Properties</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-20.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-20.png" alt="" width="570" height="187" class="aligncenter size-full wp-image-8559" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-20.png 570w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-20-300x98.png 300w" sizes="(max-width: 570px) 100vw, 570px" /></a><br />
How do you know which one is which? Once you open the properties, look at the <strong>Network </strong>under the <strong>General </strong>tab. Based on the subnet, you&#8217;ll have to assign the IP that belongs to that subnet. So, in my case this is how it looked like before I made the change.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-21.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-21.png" alt="" width="400" height="553" class="aligncenter size-full wp-image-8560" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-21.png 400w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-21-217x300.png 217w" sizes="(max-width: 400px) 100vw, 400px" /></a><br />
I know that <strong>192.168.2.0/24</strong> belongs to <strong>node02</strong>, so I&#8217;ve changed the settings from DHCP to Static IP and added <strong>192.168.2.60</strong>. Remember this IP? It was the first one that we added to node02. Scroll up if you forgot.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-22.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-22.png" alt="" width="396" height="555" class="aligncenter size-full wp-image-8561" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-22.png 396w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-22-214x300.png 214w" sizes="(max-width: 396px) 100vw, 396px" /></a><br />
Do the same for the 2nd entry. This time you have to add <strong>192.168.1.60</strong> because the subnet is <strong>192.168.1.0/24</strong>. Then, bring the cluster online.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-23.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-23.png" alt="" width="565" height="318" class="aligncenter size-full wp-image-8562" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-23.png 565w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-23-300x169.png 300w" sizes="(max-width: 565px) 100vw, 565px" /></a><br />
Now, you can install the SQL server. </p>
<h1>SQL Server installation</h1>
<p>As I mentioned earlier, make sure you have correct DNS settings and the time is in sync with AD. Before you install MS SQL, make sure you have your partitions ready. They don&#8217;t have to be like this, you can use C:\ only for everything, but ask your DBA how they want to carve the space for the DB. I am using the trial version downloaded from <a href="https://www.microsoft.com/en-us/sql-server/sql-server-downloads" rel="noopener noreferrer" target="_blank">here</a>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-24.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-24.png" alt="" width="754" height="207" class="aligncenter size-full wp-image-8563" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-24.png 754w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-24-300x82.png 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-24-585x161.png 585w" sizes="(max-width: 754px) 100vw, 754px" /></a><br />
Run the installation on both nodes using the service account <strong>svc_sql</strong>. You made this a local admin, didn&#8217;t you? Click on <strong>Installation </strong> on the left side and the first option for a <strong>new SQL Server stand-alone</strong>&#8230;<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-25.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-25.jpg" alt="" width="743" height="269" class="aligncenter size-full wp-image-8564" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-25.jpg 743w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-25-300x109.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-25-585x212.jpg 585w" sizes="(max-width: 743px) 100vw, 743px" /></a><br />
Choose license.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-26.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-26.jpg" alt="" width="324" height="161" class="aligncenter size-full wp-image-8565" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-26.jpg 324w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-26-300x149.jpg 300w" sizes="(max-width: 324px) 100vw, 324px" /></a><br />
Accept the license terms and use or do not use <strong>Microsoft Update</strong> for SQL updates.<br />
Ignore the warning for the firewall.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-27.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-27.jpg" alt="" width="477" height="141" class="aligncenter size-full wp-image-8566" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-27.jpg 477w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-27-300x89.jpg 300w" sizes="(max-width: 477px) 100vw, 477px" /></a><br />
Check the <strong>Database Engine Service</strong>, <strong>SQL Server Replication</strong>&#8230;<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-28.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-28.jpg" alt="" width="283" height="88" class="aligncenter size-full wp-image-8567" /></a><br />
&#8230;scroll down and check <strong>Client Tools Connectivity</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-29.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-29.jpg" alt="" width="276" height="54" class="aligncenter size-full wp-image-8568" /></a><br />
Click on <strong>Named instance</strong> and type your name. In my case it&#8217;s <strong>SQL2017</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-30.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-30.jpg" alt="" width="316" height="165" class="aligncenter size-full wp-image-8569" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-30.jpg 316w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-30-300x157.jpg 300w" sizes="(max-width: 316px) 100vw, 316px" /></a><br />
Leave the <strong>Service Accounts</strong> as is. We&#8217;ll change one of them later.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-31.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-31.jpg" alt="" width="579" height="240" class="aligncenter size-full wp-image-8570" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-31.jpg 579w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-31-300x124.jpg 300w" sizes="(max-width: 579px) 100vw, 579px" /></a><br />
Under <strong>Server Configuration</strong> tab, use <strong>Windows authentication mode</strong> and click <strong>Add Current User</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-32.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-32.jpg" alt="" width="586" height="426" class="aligncenter size-full wp-image-8571" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-32.jpg 586w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-32-300x218.jpg 300w" sizes="(max-width: 586px) 100vw, 586px" /></a><br />
On the <strong>Data Directories</strong> tab in the same dialog you can change the disk destinations. If you have just one <strong>C:\</strong> partition you can skip this part. If not, map the directories here. Here are mine.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-33.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-33.png" alt="" width="582" height="241" class="aligncenter size-full wp-image-8572" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-33.png 582w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-33-300x124.png 300w" sizes="(max-width: 582px) 100vw, 582px" /></a><br />
And for <strong>TempDB</strong> on the next tab in the same dialog.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-34.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-34.png" alt="" width="576" height="415" class="aligncenter size-full wp-image-8573" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-34.png 576w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-34-300x216.png 300w" sizes="(max-width: 576px) 100vw, 576px" /></a><br />
Proceed to <strong>Install</strong> until the installation completes successfully.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-35.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-35.jpg" alt="" width="599" height="143" class="aligncenter size-full wp-image-8574" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-35.jpg 599w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-35-300x72.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-35-585x140.jpg 585w" sizes="(max-width: 599px) 100vw, 599px" /></a></p>
<h2>SQL Management Tools (optional)</h2>
<p>This step is optional. If you have <strong>SSMS </strong>already installed, you can skip this part. If not, install it on a node, both or any client workstation. From the same setup menu, install SQL Management Tools (third from the top). This will take you to a MS web site where you can download the latest <strong>SMSS</strong> (SQL Server Management Studio).<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-36.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-36.jpg" alt="" width="743" height="269" class="aligncenter size-full wp-image-8575" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-36.jpg 743w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-36-300x109.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-36-585x212.jpg 585w" sizes="(max-width: 743px) 100vw, 743px" /></a></p>
<h2>SQL service account change</h2>
<p>Before you reboot, let&#8217;s change the account that runs SQL. This is mandatory for a SQL cluster. DO NOT change the account from the <strong>Services </strong>console, instead open <strong>SQL 2017 Configuration Manager</strong>.<br />
Do this on both nodes. Select where it says <strong>SQL Server Services</strong> on the left and then right-click on <strong>SQL Server (SQL2017)</strong> on the right and choose <strong>Properties</strong>.<br />
Enter the SQL service account, its password and click <strong>Apply</strong>. This will reset the SQL service and change it to run under the domain service account. Do not reboot yet.</p>
<h1>Dynamic ports and firewall</h1>
<p>Because we are using a named SQL instance, the DB engine assigns a random dynamic port for the listener. Instead of opening a range of ports on the firewall, we can restrict the listener to a static port and then open the firewall for that port only. Do this on both nodes. In the same <strong>SQL 2017 Configuration Manager</strong>, look for <strong>SQL Server Network Configuration</strong> on the left, expand it and select <strong>Protocols for SQL2017</strong> or whatever you named your instance. Right-click where it says <strong>TCP/IP</strong> on the right and choose <strong>Properties</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-37.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-37.jpg" alt="" width="492" height="235" class="aligncenter size-full wp-image-8576" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-37.jpg 492w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-37-300x143.jpg 300w" sizes="(max-width: 492px) 100vw, 492px" /></a><br />
Click on the second tab <strong>IP Addresses</strong> and scroll all the way down where it says <strong>TCP Dynamic Ports</strong>. Delete that value, leave it blank and in the next field <strong>TCP Port</strong> below, enter a random TCP port from <strong>49152-65535</strong>. I&#8217;ll use <strong>50000 </strong>for both nodes. You need to restart the SQL service for this change to take effect, but we&#8217;ll reboot, so no need for that. But, if you have your Windows Firewall enabled, you have to open these TCP ports. Run these command from an elevated PowerShell prompt.</p>
<pre class="brush: bash; title: ; notranslate">
New-NetFirewallRule -Name &quot;SQL2017 Named Instance (in)&quot; -Description &quot;SQL2017 Named Instance&quot; `
-DisplayName &quot;SQL2017 Named Instance&quot; -Enabled:True -Profile Domain,Public,Private `
-Direction Inbound -Action Allow -Protocol TCP -LocalPort 50000
New-NetFirewallRule -Name &quot;SQL Server Rule (in)&quot; -Description &quot;SQL Server Rule&quot; `
-DisplayName &quot;SQL Rule&quot; -Enabled:True -Profile Domain,Public,Private `
-Direction Inbound -Action Allow -Protocol TCP -LocalPort 1433
New-NetFirewallRule -Name &quot;SQL Server Browser Rule (in)&quot; -Description &quot;SQL Server Browser Rule&quot; `
-DisplayName &quot;SQL Browser Rule&quot; -Enabled:True -Profile Domain,Public,Private `
-Direction Inbound -Action Allow -Protocol UDP -LocalPort 1434
New-NetFirewallRule -Name &quot;SQL Server AlwaysOn Replication (in)&quot; -Description &quot;SQL Server AlwaysOn Replication&quot; `
-DisplayName &quot;SQL Server AlwaysOn Replication&quot; -Enabled:True -Profile Domain,Public,Private `
-Direction Inbound -Action Allow -Protocol TCP -LocalPort 5022
</pre>
<p>Now, you can reboot.</p>
<h1>AlwaysOn</h1>
<p>Log as the SQL service account <strong>svc_sql</strong> and open <strong>SQL Configuration Manager</strong>. You have to do this on both nodes. Similarly to what you did when you change the SQL service account, do the same.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-38.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-38.jpg" alt="" width="856" height="455" class="aligncenter size-full wp-image-8577" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-38.jpg 856w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-38-300x159.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-38-768x408.jpg 768w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-38-585x311.jpg 585w" sizes="(max-width: 856px) 100vw, 856px" /></a><br />
Select <strong>SQL Server Services</strong>, right-click <strong>SQL Server (SQL2017)</strong> and check <strong>Enable AlwaysOn Availability Groups</strong> under <strong>AlwaysOn High Availability</strong> tab.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-39.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-39.jpg" alt="" width="797" height="331" class="aligncenter size-full wp-image-8578" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-39.jpg 797w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-39-300x125.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-39-768x319.jpg 768w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-39-585x243.jpg 585w" sizes="(max-width: 797px) 100vw, 797px" /></a><br />
Restart the SQL service on both nodes. Once completed, open SSMS, connect to a node and create a new database.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-40.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-40.jpg" alt="" width="361" height="264" class="aligncenter size-full wp-image-8579" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-40.jpg 361w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-40-300x219.jpg 300w" sizes="(max-width: 361px) 100vw, 361px" /></a><br />
I&#8217;ll name my database <strong>MyDB</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-41.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-41.jpg" alt="" width="501" height="205" class="aligncenter size-full wp-image-8580" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-41.jpg 501w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-41-300x123.jpg 300w" sizes="(max-width: 501px) 100vw, 501px" /></a><br />
Make sure you backup the database. You can&#8217;t proceed without this step.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-42.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-42.jpg" alt="" width="514" height="250" class="aligncenter size-full wp-image-8581" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-42.jpg 514w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-42-300x146.jpg 300w" sizes="(max-width: 514px) 100vw, 514px" /></a><br />
Little further below, right-click on <strong>Always On High Availability</strong> and click on <strong>New Availability Group Wizard</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-43.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-43.jpg" alt="" width="420" height="101" class="aligncenter size-full wp-image-8582" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-43.jpg 420w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-43-300x72.jpg 300w" sizes="(max-width: 420px) 100vw, 420px" /></a><br />
Specify a name for the availability group.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-44.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-44.jpg" alt="" width="574" height="198" class="aligncenter size-full wp-image-8583" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-44.jpg 574w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-44-300x103.jpg 300w" sizes="(max-width: 574px) 100vw, 574px" /></a><br />
Select the database that we just created.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-45.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-45.jpg" alt="" width="582" height="131" class="aligncenter size-full wp-image-8584" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-45.jpg 582w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-45-300x68.jpg 300w" sizes="(max-width: 582px) 100vw, 582px" /></a><br />
Click on <strong>Add Replica</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-46.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-46.jpg" alt="" width="581" height="288" class="aligncenter size-full wp-image-8585" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-46.jpg 581w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-46-300x149.jpg 300w" sizes="(max-width: 581px) 100vw, 581px" /></a><br />
Connect to node02.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-47.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-47.jpg" alt="" width="574" height="361" class="aligncenter size-full wp-image-8586" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-47.jpg 574w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-47-300x189.jpg 300w" sizes="(max-width: 574px) 100vw, 574px" /></a><br />
I want automatic failover which means it&#8217;s a synchronous commit.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-48.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-48.jpg" alt="" width="580" height="218" class="aligncenter size-full wp-image-8587" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-48.jpg 580w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-48-300x113.jpg 300w" sizes="(max-width: 580px) 100vw, 580px" /></a><br />
Choose <strong>Automatic Seeding</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-49.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-49.jpg" alt="" width="589" height="467" class="aligncenter size-full wp-image-8588" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-49.jpg 589w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-49-300x238.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-49-585x464.jpg 585w" sizes="(max-width: 589px) 100vw, 589px" /></a><br />
Don&#8217;t worry about the listener.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-50.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-50.jpg" alt="" width="577" height="221" class="aligncenter size-full wp-image-8589" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-50.jpg 577w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-50-300x115.jpg 300w" sizes="(max-width: 577px) 100vw, 577px" /></a><br />
After 10-20 seconds the configuration should complete.<br />
Now, we need to add a listener. Expand the <strong>Availability Groups</strong>, right-click <strong>Availability Group Listeners</strong> and select <strong>Add Listener</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-51.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-51.jpg" alt="" width="382" height="218" class="aligncenter size-full wp-image-8590" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-51.jpg 382w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-51-300x171.jpg 300w" sizes="(max-width: 382px) 100vw, 382px" /></a><br />
Give listener a name (in my case <strong>MyListener</strong>), you can choose a port (I used the default <strong>1433</strong>, you can choose a random port but don&#8217;t forget to open the firewall) and add the other two IPs as static IPs.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-52.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-52.jpg" alt="" width="506" height="195" class="aligncenter size-full wp-image-8591" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-52.jpg 506w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-52-300x116.jpg 300w" sizes="(max-width: 506px) 100vw, 506px" /></a><br />
Right-click the availability group and click on <strong>Show Dashboard</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-53.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-53.jpg" alt="" width="852" height="504" class="aligncenter size-full wp-image-8592" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-53.jpg 852w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-53-300x177.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-53-768x454.jpg 768w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-53-585x346.jpg 585w" sizes="(max-width: 852px) 100vw, 852px" /></a><br />
Everything should be with green checkmarks and both states should be synchronized. The availability group (and the database) are configured for automatic failover, but you can do manual failover if you want. Right-click the availability group and click on <strong>Failover</strong>. This is how my manual failover looks like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-54.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-54.jpg" alt="" width="576" height="202" class="aligncenter size-full wp-image-8593" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-54.jpg 576w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-54-300x105.jpg 300w" sizes="(max-width: 576px) 100vw, 576px" /></a><br />
At this point you have a fully functional AlwaysOn cluster. </p>
<h1>Test the failover (optional)</h1>
<p>We&#8217;ll use a sample populated table to run some queries from PowerShell. Then, we&#8217;ll stop one node and watch the outcome. In order to do the test, open up SMSS, log as <strong>svc_sql</strong> and connect to the listener directly.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-55.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-55.jpg" alt="" width="479" height="227" class="aligncenter size-full wp-image-8594" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-55.jpg 479w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-55-300x142.jpg 300w" sizes="(max-width: 479px) 100vw, 479px" /></a><br />
Click on <strong>New Query</strong> from the top.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-56.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-56.jpg" alt="" width="394" height="236" class="aligncenter size-full wp-image-8595" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-56.jpg 394w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-56-300x180.jpg 300w" sizes="(max-width: 394px) 100vw, 394px" /></a><br />
Insert these statements. They&#8217;ll create a SQL login mapped from the domain name (in my case <strong>klimenta</strong>) and a table in the <strong>MyDB </strong>database called <strong>COLORS</strong>. Replace the values that match your domain name and the database. Execute the first part (<strong>CREATE LOGIN</strong>) on <strong>node02 </strong>too.</p>
<pre class="brush: sql; title: ; notranslate">
CREATE LOGIN &#x5B;AD-DOMAIN\klimenta]  
    FROM WINDOWS  
    WITH DEFAULT_DATABASE = &#x5B;MyDB];
USE MyDB;
CREATE TABLE COLORS (ID INT, NAME VARCHAR(10));
INSERT INTO COLORS VALUES(1,'RED');
INSERT INTO COLORS VALUES(2,'YELLOW');
INSERT INTO COLORS VALUES(3,'BLUE');
INSERT INTO COLORS VALUES(4,'WHITE');
GO
</pre>
<p>Double-click the login that you just created, click on <strong>User Mapping</strong> and put a checkmark next to <strong>MyDB</strong> database.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-57.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-57.jpg" alt="" width="698" height="321" class="aligncenter size-full wp-image-8596" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-57.jpg 698w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-57-300x138.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-57-585x269.jpg 585w" sizes="(max-width: 698px) 100vw, 698px" /></a><br />
Right-click the database, choose <strong>Properties </strong>then click on <strong>Permissions</strong>. Select the username and make sure you have <strong>Connect </strong>and <strong>Select </strong>permissions.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-58.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-58.jpg" alt="" width="754" height="465" class="aligncenter size-full wp-image-8597" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-58.jpg 754w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-58-300x185.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-58-585x361.jpg 585w" sizes="(max-width: 754px) 100vw, 754px" /></a><br />
From a separate workstation/server, you can use even the domain controller, log as the username (<strong>klimenta</strong>) that you just granted right to the MyDB database. Open up PowerShell ISE and run this script. Replace the values for the listener and the database. It&#8217;s a script that connects to the database and spits the contect of the COLORS table indefinitely. Use CTRL-C to break.</p>
<pre class="brush: powershell; title: ; notranslate">
$Server = 'tcp:mylistener,1433'    
$database = 'MyDB'
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = &quot;server=$($Server);database=$($Database);trusted_connection=true;MultiSubnetFailover=True;&quot;
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$x=0
while ($true) {
    $Command.CommandText = 'SELECT * FROM COLORS'
    $Reader = $Command.ExecuteReader()
    $Datatable = New-Object System.Data.DataTable
    $Datatable.Load($Reader)
    $Datatable
    Start-Sleep -s 5
    Write-Host($x, &quot;---&quot;)
    $x++;
}
$Connection.Close()  
</pre>
<p>Once you see the output, shutdown the primary node or do a manual failover. You&#8217;ll notice that there is no interruption in the program flow. The only thing that changes is the IP of the listener.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/07/P132-59.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/07/P132-59.jpg" alt="" width="395" height="362" class="aligncenter size-full wp-image-8598" srcset="https://blog.andreev.it/wp-content/uploads/2019/07/P132-59.jpg 395w, https://blog.andreev.it/wp-content/uploads/2019/07/P132-59-300x275.jpg 300w" sizes="(max-width: 395px) 100vw, 395px" /></a></p>
<h1>Links</h1>
<p><a href="https://youtu.be/GM7H9fba9cQ" rel="noopener noreferrer" target="_blank">YouTube (AWS)</a><br />
<a href="https://docs.microsoft.com/en-us/sql/database-engine/availability-groups/windows/overview-of-always-on-availability-groups-sql-server?view=sql-server-2017" rel="noopener noreferrer" target="_blank">Microsoft</a><br />
<a href="https://www.red-gate.com/simple-talk/sql/database-administration/the-posh-dba-accessing-sql-server-from-powershell/" rel="noopener noreferrer" target="_blank">PowerShell</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2019/07/windows-ms-sql-2017-with-alwayson-named-instance-wsfc-on-aws/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWS: Hybrid DNS resolution between on-prem and AWS</title>
		<link>https://blog.andreev.it/2019/01/145-aws-hybrid-dns-resolution-between-on-prem-and-aws/</link>
					<comments>https://blog.andreev.it/2019/01/145-aws-hybrid-dns-resolution-between-on-prem-and-aws/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 30 Jan 2019 16:04:38 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Hybrid DNS]]></category>
		<category><![CDATA[on-prem]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=4364</guid>

					<description><![CDATA[Lately I was playing with Docker and the AWS EFS file systems and I&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Lately I was playing with Docker and the AWS EFS file systems and I realized that I can&#8217;t access my new NFS file system because of the DNS resolution. The reason being that I use a DNS that&#8217;s at home and this DNS has no clue about any AWS resources. This is how my setup looks like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-01.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-01.jpg" alt="" width="1312" height="766" class="aligncenter size-full wp-image-8409" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-01.jpg 1312w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-01-300x175.jpg 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-01-1024x598.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-01-768x448.jpg 768w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-01-1170x683.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-01-585x342.jpg 585w" sizes="(max-width: 1312px) 100vw, 1312px" /></a><br />
I have two domain controllers, DC01 and DC02. The first one is at home/on-prem and the other one is in AWS. They are on a different subnets. I also have a site-to-site VPN connection between the two. All of my resources use the DNS servers that I provide. This means that the AWS DNS that comes as default when you create a new VPC was never used. I have a specific DHCP Option Set in AWS that I use to provide my DNS servers to all of my AWS resources.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-02.png" alt="" width="1336" height="305" class="aligncenter size-full wp-image-8410" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-02.png 1336w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-02-300x68.png 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-02-1024x234.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-02-768x175.png 768w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-02-1170x267.png 1170w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-02-585x134.png 585w" sizes="(max-width: 1336px) 100vw, 1336px" /></a><br />
And here is the problem. When I created a new EFS file system, I tried to mount it, but my DNS had no clue where this resource is. The hostname for the EFS is not publicly resolvable. On top of that, you can&#8217;t resolve this hostname from on-prem over VPN and Direct Connect even if you use the provided AWS DNS as a forwarder. The solution before was to build a DNS server in the cloud and make it as a forwarder. As of November 2018, AWS expanded the Route 53 DNS and now you can create inbound and outbound endpoints that do this for you. In my case, I needed amazonaws.com to be resolved by my DNS. All I have to do is to create an inbound endpoint in Route 53 and tell my DNS servers to use the IPs provided by Route 53.<br />
Here is what I did.<br />
In Route 53, click on <strong>Inbound endpoints</strong>. Click on <strong>Create inbound endpoint</strong>. Fill out the values by specifying a name for the inbound endpoint, the VPC where your resources reside and a security group that allow access. I am not quite sure what security levels are needed here, I assume TCP/UDP 53, so I assigned a security group that gives access to all my AWS resources to the resources on-prem. Try with TCP/UDP 53 first and see if it works.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-03.png" alt="" width="1015" height="553" class="aligncenter size-full wp-image-8411" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-03.png 1015w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-03-300x163.png 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-03-768x418.png 768w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-03-585x319.png 585w" sizes="(max-width: 1015px) 100vw, 1015px" /></a><br />
Specify two subnets and let AWS choose the IPs. These are the actual DNS server IPs that AWS will provide for you.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-04.png" alt="" width="1012" height="938" class="aligncenter size-full wp-image-8412" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-04.png 1012w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-04-300x278.png 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-04-768x712.png 768w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-04-585x542.png 585w" sizes="(max-width: 1012px) 100vw, 1012px" /></a><br />
Click <strong>Submit</strong>. Once completed you&#8217;ll see your inbound endpoint ready.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-05.png" alt="" width="1107" height="331" class="aligncenter size-full wp-image-8413" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-05.png 1107w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-05-300x90.png 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-05-1024x306.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-05-768x230.png 768w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-05-585x175.png 585w" sizes="(max-width: 1107px) 100vw, 1107px" /></a><br />
If you click on the endpoint, you&#8217;ll see the IPs that AWS provides to you.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-06.png" alt="" width="1279" height="388" class="aligncenter size-full wp-image-8414" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-06.png 1279w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-06-300x91.png 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-06-1024x311.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-06-768x233.png 768w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-06-1170x355.png 1170w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-06-585x177.png 585w" sizes="(max-width: 1279px) 100vw, 1279px" /></a><br />
Now, go back to your on-prem DNS and create a conditional forwarder for amazonaws.com.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-07.png" alt="" width="540" height="239" class="aligncenter size-full wp-image-8415" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-07.png 540w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-07-300x133.png 300w" sizes="(max-width: 540px) 100vw, 540px" /></a><br />
Specify the domain amazonaws.com and enter the two IPs that were provided to you.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-08.png" alt="" width="789" height="715" class="aligncenter size-full wp-image-8416" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-08.png 789w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-08-300x272.png 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-08-768x696.png 768w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-08-585x530.png 585w" sizes="(max-width: 789px) 100vw, 789px" /></a><br />
I made sure that they are stored in AD, so both DCs can get the settings. By default, a conditional forwarder is not stored in AD, which means it won&#8217;t replicate.<br />
Now that everything is configured, I can resolve my EFS filesystem from my on-prem server.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/01/P122-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/01/P122-09.png" alt="" width="623" height="301" class="aligncenter size-full wp-image-8417" srcset="https://blog.andreev.it/wp-content/uploads/2019/01/P122-09.png 623w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-09-300x145.png 300w, https://blog.andreev.it/wp-content/uploads/2019/01/P122-09-585x283.png 585w" sizes="(max-width: 623px) 100vw, 623px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2019/01/145-aws-hybrid-dns-resolution-between-on-prem-and-aws/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Windows, CentOS, FreeBSD: ssh, RDP &#8211; Bypass your corporate firewall</title>
		<link>https://blog.andreev.it/2018/03/125-ssh-rdp-bypass-your-corporate-firewall/</link>
					<comments>https://blog.andreev.it/2018/03/125-ssh-rdp-bypass-your-corporate-firewall/#comments</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Fri, 23 Mar 2018 17:04:18 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[bypass]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[freebsd]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=3765</guid>

					<description><![CDATA[If you are behind a firewall and want to access some resources over SSH&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>If you are behind a firewall and want to access some resources over SSH or RDP, most likely you won&#8217;t be able to do that. It&#8217;s because most of the corporate firewalls allow only ports 80 and 443 outbound. But you can still bypass that by tunneling everything over port 443. You will need a software called shellinabox to tunnel SSH over 443 and RDP gateway to tunnel the RDP traffic over 443. I&#8217;ll present the shellinabox solution for both CentOS 7 and FreeBSD 11. Both of these servers will be sitting somewhere in the cloud or behind your home firewall. The only requirement is to have port 443 opened and accessible on Internet. You might have a public IP or your home firewall will forward the traffic to 443, it doesn&#8217;t matter. Another option for connecting to any port is to use putty and a Linux/FreeBSD instance. I&#8217;ll describe that option last.</p>
<h1>CentOS 7</h1>
<p>shellinabox doesn&#8217;t come up with the default packages, so you have to install the EPEL release first. </p>
<pre class="brush: bash; title: ; notranslate">
yum install epel-release
yum install shellinabox
systemctl enable shellinaboxd
</pre>
<p>Edit the configuration file for shellinabox which is <strong>/etc/sysconfig/shellinaboxd</strong>. Make sure it looks like this. </p>
<pre class="brush: bash; title: ; notranslate">
# Shell in a box daemon configuration
# For details see shellinaboxd man page
# Basic options
USER=shellinabox
GROUP=shellinabox
CERTDIR=/var/lib/shellinabox
PORT=4200
OPTS=&quot;--css white-on-black.css -t -s /:SSH:localhost&quot;
#OPTS=&quot;--css color.css -t -s /:SSH:localhost&quot;
</pre>
<p>shellinabox runs on port 4200 by default. You can change it to run on 443, but you have to run as root. A better solution is to install Apache and use the mod_proxy so the Apache will listen on 443 and forward the traffic to 4200. </p>
<pre class="brush: bash; title: ; notranslate">
yum install httpd mod_ssl
systemctl enable httpd
</pre>
<p>Create the configuration file for the Apache server. In my case, I&#8217;ll access the SSH over HTTPS as sshtest.iandreev.com. Change the config below to suit your needs. </p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/httpd/conf.d
touch httpd-vhosts.conf
</pre>
<p>Edit httpd-vhosts.conf and paste the following. </p>
<pre class="brush: bash; title: ; notranslate">
&lt;VirtualHost *:443&gt;
    SSLEngine On
    SSLCertificateFile /etc/pki/tls/certs/sshtest.iandreev.com.crt
    ServerAdmin klimenta@iandreev.com
    ServerName sshtest.iandreev.com
    ErrorLog &quot;/var/log/httpd/sshtest.iandreev.com-error_log&quot;
    CustomLog &quot;/var/log/httpd/sshtest.iandreev.com-access_log&quot; combined
    ProxyRequests On
    ProxyPreserveHost On
    &lt;Proxy *&gt;
        AuthUserFile /var/www/sshtest.iandreev.com/.htpasswd
        AuthName EnterPassword
        AuthType Basic
        require user ssh.admin
        Order deny,allow
        Allow from all
    &lt;/Proxy&gt;
    ProxyPass / http://localhost:4200/
    ProxyPassReverse / http://localhost:4200/
&lt;/VirtualHost&gt;
</pre>
<p>HTTPS requires a certificate, we&#8217;ll create a fake one. If you have a valid certificate, just put it under <strong>/etc/pki/tls/certs</strong> as <strong>sshtest.iandreev.com.crt</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/pki/tls/certs
./make-dummy-cert sshtest.iandreev.com.crt
</pre>
<p>shellinabox when started will give you a SSH prompt so you can login to your server. A more secure solution is to protect the access even more with a username and password. Anytime you access your server, you&#8217;ll get prompted with a username and password and then you&#8217;ll get prompted with your SSH credentials.</p>
<pre class="brush: bash; title: ; notranslate">
cd /var/www
mkdir sshtest.iandreev.com
cd sshtest.iandreev.com
htpasswd -c .htpasswd ssh.admin
cd ..
chown -R apache:apache sshtest.iandreev.com
</pre>
<p>I&#8217;ve created a user called ssh.admin and the commands above will ask you for a password.<br />
Now, it&#8217;s time to start shellinabox.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl start httpd
systemctl start shellinaboxd
</pre>
<p>On a laptop behind your comporate firewall, go to https://sshtest.yourdomain.com and you should get prompted for ssh.admin&#8217;s password. Once you pass that you&#8217;ll see the login prompt in your browser. From here you can SSH to any server that has port 22 opened.<br />
shellinabox comes with two styles. If you see above in it&#8217;s config, we provided these two lines.</p>
<pre class="brush: bash; title: ; notranslate">
OPTS=&quot;--css white-on-black.css -t -s /:SSH:localhost&quot;
#OPTS=&quot;--css color.css -t -s /:SSH:localhost&quot;
</pre>
<p>If you prefer black on white background, uncomment the last line, save the config file and restart shellinabox.<br />
Depending on your CentOS install, you might have firewall and SElinux enabled. If these are not configured, shellinabox won&#8217;t work. For the firewall, you&#8217;ll have to allow port 443 inbound. </p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --add-service=https --permanent
firewall-cmd --reload
</pre>
<p>For SElinux, you&#8217;ll have to allow Apache to make outbound connections.</p>
<pre class="brush: bash; title: ; notranslate">
/usr/sbin/setsebool -P httpd_can_network_connect 1
</pre>
<p>At the end, it will look like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-01.png" alt="" width="698" height="281" class="aligncenter size-full wp-image-8195" /></a><br />
&#8230;and this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-02.png" alt="" width="475" height="219" class="aligncenter size-full wp-image-8196" /></a></p>
<h1>FreeBSD 11</h1>
<p>We have to install Apache and shellinabox first. </p>
<pre class="brush: bash; title: ; notranslate">
pkg install shellinabox apache24
</pre>
<p>Make sure they start on boot. Add these two lines in <strong>/etc/rc.d</strong></p>
<pre class="brush: bash; title: ; notranslate">
apache24_enable=&quot;YES&quot;
shellinaboxd_enable=&quot;YES&quot;
shellinaboxd_flags=&quot;--disable-ssl --css=/usr/local/www/sshtest.iandreev.com/style.css&quot;
</pre>
<p>Go to the Apache config directory and edit the config file <strong>/usr/local/etc/apache24/httpd.conf</strong>. Make sure these lines are uncommented. </p>
<pre class="brush: bash; title: ; notranslate">
Include etc/apache24/extra/httpd-vhosts.conf
LoadModule authn_socache_module libexec/apache24/mod_authn_socache.so
LoadModule socache_shmcb_module libexec/apache24/mod_socache_shmcb.so
LoadModule ssl_module libexec/apache24/mod_ssl.so
Include etc/apache24/extra/httpd-ssl.conf
LoadModule proxy_module libexec/apache24/mod_proxy.so
LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so
ServerName www.example.com:80
</pre>
<p>Go to <strong>/usr/local/etc/apache24/extra</strong> folder and make sure you have the definitiopn for the virtual host there. Change it to suit your needs. </p>
<pre class="brush: bash; title: ; notranslate">
&lt;VirtualHost *:443&gt;
    SSLEngine On
    SSLCertificateFile /usr/local/share/certs/sshtest.iandreev.com.crt
    SSLCertificateKeyFile /usr/local/share/certs/sshtest.iandreev.com.key
    ServerAdmin klimenta@iandreev.com
    ServerName sshtest.iandreev.com
    ErrorLog &quot;/var/log/sshtest.iandreev.com-error_log&quot;
    CustomLog &quot;/var/log/sshtest.iandreev.com-access_log&quot; combined
    ProxyRequests On
    ProxyPreserveHost On
    &lt;Proxy *&gt;
        AuthUserFile /usr/local/www/sshtest.iandreev.com/.htpasswd
        AuthName EnterPassword
        AuthType Basic
        require user ssh.admin
        Order deny,allow
        Allow from all
    &lt;/Proxy&gt;
    ProxyPass / http://localhost:4200/
    ProxyPassReverse / http://localhost:4200/
&lt;/VirtualHost&gt;
</pre>
<p>In the same directory, edit <strong>httpd-ssl.conf</strong> file and make sure it looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
SSLRandomSeed startup file:/dev/urandom 512
Listen 443
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLHonorCipherOrder on
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3
SSLPassPhraseDialog  builtin
SSLSessionCache        &quot;shmcb:/var/run/ssl_scache(512000)&quot;
SSLSessionCacheTimeout  300
</pre>
<p>We&#8217;ll protect shellinabox with extra username (ssh.admin) and password. </p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/www
mkdir sshtest.iandreev.com
cd sshtest.iandreev.com
htpasswd -c .htpasswd ssh.admin
</pre>
<p>We&#8217;ll need a certificate for the HTTPS site. Use your own or create a fake one. Hit ENTER for everything prompted. It&#8217;s a fake certificate.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/share/certs
openssl genrsa -out sshtest.iandreev.com.key 2048
openssl req -new -key sshtest.iandreev.com.key -out sshtest.iandreev.com.csr
openssl x509 -req -days 3650 -in sshtest.iandreev.com.csr -signkey sshtest.iandreev.com.key -out sshtest.iandreev.com.crt
</pre>
<p>Unlike CentOS, FreeBSD shellinabox doesn&#8217;t come up with CSS files for the color, so we can use these two. Copy these files under <strong>/usr/local/www/sshtest.iandreev.com</strong> as <strong>blackonwhite.css</strong> and <strong>whiteonblack.css</strong>.<br />
This is <strong>blackonwhite.css</strong>. Click to expand. </p>
<pre class="brush: css; collapse: true; light: false; title: ; toolbar: true; notranslate">
#vt100 .ansiDefR {
  color:            #ffffff;
}

#vt100 .bgAnsiDefR {
  background-color: #123450;
}

#vt100 #scrollable.inverted .ansiDefR {
  color:            #000000;
}

#vt100 #scrollable.inverted .bgAnsiDefR {
  background-color: #ffffff;
}

#vt100 .ansiDefR {
  color:            #ffdfd0;
}

#vt100 .bgAnsiDefR {
  background-color: #010203;
}

#vt100 #scrollable.inverted .ansiDefR {
  color:            #002030;
}

#vt100 #scrollable.inverted .bgAnsiDefR {
  background-color: #1f1fff;
}
</pre>
<p>This is <strong>whiteonblack.css</strong>. Click to expand.</p>
<pre class="brush: css; collapse: true; light: false; title: ; toolbar: true; notranslate">
#vt100 #cursor.bright {
  background-color: white;
  color:            black;
}

#vt100 #cursor.dim {
  background-color: black;
  opacity:          0.2;
  -moz-opacity:     0.2;
  filter:           alpha(opacity=20);
}

#vt100 #scrollable {
  color:            #ffffff;
  background-color: #000000;
}

#vt100 #scrollable.inverted {
  color:            #000000;
  background-color: #ffffff;
}

#vt100 .ansiDef {
  color:            #ffffff;
}

#vt100 .ansiDefR {
  color:            #000000;
}

#vt100 .bgAnsiDef {
  background-color: #000000;
}

#vt100 .bgAnsiDefR {
  background-color: #ffffff;
}

#vt100 #scrollable.inverted .ansiDef {
  color:            #000000;
}

#vt100 #scrollable.inverted .ansiDefR {
  color:            #ffffff;
}

#vt100 #scrollable.inverted .bgAnsiDef {
  background-color: #ffffff;
}

#vt100 #scrollable.inverted .bgAnsiDefR {
  background-color: #000000;
}
</pre>
<p>Copy one of them to be your style. Anytime you change the style, restart shellinabox.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/www/sshtest.iandreev.com
cp blackonwhite.css style.css
cd ..
chown -R www:www sshtest.iandreev.com
</pre>
<p>Finally, start Apache and shellinabox. </p>
<pre class="brush: bash; title: ; notranslate">
service shellinaboxd start
service apache24 start
</pre>
<p>Access your server from a laptop behind your corporate firewall as https://sshtest.domain.com.</p>
<h1>Windows 2016</h1>
<p>You will need a Windows 2016 server with a public IP and port 443 allowed or you can use a Windows server behind your home network as long as port 443 is allowed. In order to bypass the RDP restriction, we&#8217;ll tunnel the RDP traffic over HTTPS using Remote Desktop Gateway.<br />
From the Server Manager, go to Add Roles and Features. Select <strong>Remote Desktop Services</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-03.png" alt="" width="790" height="556" class="aligncenter size-full wp-image-8197" /></a><br />
Click <strong>Next </strong>2-3 times and then select <strong>Remote Desktop Gateway</strong>. Click Next again and accept all the defaults. Windows will install some other components for you.<br />
Once everything is installed, from the Server Manager&#8217;s menu click on <strong>Tools</strong>, <strong>Remote Desktop Services</strong> and then <strong>Remote Desktop Gateway Manager</strong>.<br />
Click on the server name and in the middle pane you&#8217;ll see what you have to do.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-04.png" alt="" width="972" height="456" class="aligncenter size-full wp-image-8198" /></a><br />
Click on the first link, <strong>View or modify certificate properties</strong>. Choose to create a fake certificate or you can import your own. It has to be in p12 format, not PEM.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-05.png" alt="" width="499" height="590" class="aligncenter size-full wp-image-8199" /></a><br />
If you decide to go with a fake certificate, enter the FQDN of the server, e.g sshtest.iandreev.com. You will have to make sure that sshtest.iandreev.com resolves to the public IP of the Windows box or if you have an internal server in your home lab, then the external IP of your cable/DSL modem. Then just click on the button <strong>Create and Import Certificate</strong>, enter the FQDN sshtest.iandreev.com and then click <strong>OK </strong>when prompted. Click <strong>Apply </strong>and <strong>OK </strong>to go back.<br />
At this point, you might want to create a user or a group that you can allow access to the Gateway.<br />
I created a user called RDP. Back in the RD Gateway Manager, select <strong>Policies </strong>under the server name, right-click on it and choose <strong>Create New Authorization Policies</strong>. Choose the option to create both RD CAP and RD RAP policies. Here is what I did in the wizard config.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-06.png" alt="" width="958" height="600" class="aligncenter size-full wp-image-8200" /></a><br />
I choose BUILTIN\Users to be able to use the Gateway. The generic user RDP that I created is by default a member of the users group.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-07.png" alt="" width="952" height="598" class="aligncenter size-full wp-image-8201" /></a><br />
Select the default <strong>Enable device redirection for all client devices</strong>.<br />
Check both checkmarks for <strong>Idle Timeout</strong> and <strong>Session Timeout</strong>. This is optional, but it&#8217;s good to have.<br />
Click Next and then create the <strong>Resource Authorization Policy</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-08.png" alt="" width="957" height="598" class="aligncenter size-full wp-image-8202" /></a><br />
Accept the same group (<strong>BUILTIN\Users</strong>).<br />
Choose the option at the bottom, <strong>Allow users to connect to any network resource (computer)</strong>.<br />
Choose the first option, <strong>Allow connections only to port 3389</strong>.<br />
Click <strong>Next </strong>and <strong>Finish</strong>.<br />
So, how do you use this solution now? Easy&#8230;<br />
All you have to do is go to your corporate laptop and create a new RDP connection. Under the General tab enter the IP address of the Windows box that you want to reach. This is the box that listens on 3389 and that you are not able to reach directly. Mind that the Windows server that we just built is a gateway, so the Windows RD Gateway server should be able to talk to the destination server over 3389 and your corporate laptop will talk to Windows RD Gateway server over 443.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-09.png" alt="" width="542" height="580" class="aligncenter size-full wp-image-8203" /></a><br />
Click on the <strong>Advanced </strong>tab and then the <strong>Settings </strong>button. Select to <strong>Use these RD Gateway server settings</strong> and enter the FQDN (sshtest.iandreev.com) of the RD Gateway server that we just built.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-10.png" alt="" width="539" height="535" class="aligncenter size-full wp-image-8204" /></a><br />
Once you are done, click <strong>Connect </strong>and you should get prompted to enter the credentials for the RD Gateway (in my case the username and password for the RDP user) and then you&#8217;ll have to enter the username and password for the destination server.<br />
NOTE: Make sure you use .\rdp for the username, not rdp. You can also get an error saying that the identity of the RD Gateway can&#8217;t be verified. This is most likely if you messed up the certificate and it doesn&#8217;t match the hostname. In that case, the RDP client will allow you to view the certificate. Then copy it to a file and import it on the local machine under the Trusted Root Cert Authorities. </p>
<h1>Tunnel over putty</h1>
<p>Let&#8217;s say that your corporate firewall allows only port 443 outbound. In this case, we&#8217;ll build a Linux/BSD server with a public IP and change the SSH listener port from 22 to 443. For this, edit <strong>sshd_config</strong> under <strong>/etc/ssh/sshd_config</strong> or <strong>/usr/local/etc/ssh/sshd_config</strong>. Look for the directive <strong>Port 22</strong> and change it to <strong>Port 443</strong>. Restart the ssh service.<br />
On your client machine behind the corporate firewall, open putty and under Session enter the public IP of your Linux/BSD server and port 443 so it looks like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-11.png" alt="" width="453" height="197" class="aligncenter size-full wp-image-8205" /></a><br />
Now, expand the <strong>Connection </strong>on the left side, then <strong>SSH </strong>and select <strong>Tunnels</strong>. For the <strong>source port</strong> enter 3390 and for the <strong>destination </strong>enter the IP of your Windows box where you want to connect.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/03/P102-12.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/03/P102-12.png" alt="" width="448" height="200" class="aligncenter size-full wp-image-8206" /></a><br />
Finally, save this session, open it and login to the Linux server to establish the tunnel. You should be able to run the RDP client (mstsc) and RDP to 127.0.0.1:3390. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2018/03/125-ssh-rdp-bypass-your-corporate-firewall/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>CentOS: Install Chef server on CentOS 7, workstation on Windows + managing a node</title>
		<link>https://blog.andreev.it/2018/01/119-centos-chef-install-chef-server-centos-7-workstation-windows-managing-node/</link>
					<comments>https://blog.andreev.it/2018/01/119-centos-chef-install-chef-server-centos-7-workstation-windows-managing-node/#comments</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Thu, 18 Jan 2018 21:02:46 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[Chef]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=3522</guid>

					<description><![CDATA[In this post I&#8217;ll explain how to install a Chef server on CentOS 7&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this post I&#8217;ll explain how to install a Chef server on CentOS 7 server. A Chef server is usually managed by a Chef workstation and the servers that we manage with the workstation via the server are called Chef nodes. For more detailed info, go to https://learn.chef.io. So, we&#8217;ll install Chef server on CentOS 7, a Chef workstation on Windows 10 and bootstrap a Chef node on CentOS 7 and a Chef node on Windows 2012R2. Then, we&#8217;ll create a cookbook that will do something and then explain a couple of commands that are commonly used. The hostnames in this post are <strong>chef-server.chef.local, chef-wks.chef.local</strong>, <strong>chef-node.chef.local</strong> for the CentOS node and <strong>chef-node-win</strong> for the Windows node.</p>
<h1>Chef server</h1>
<p>Go to https://downloads.chef.io/chef-server and download the RPM for Red Hat Linux. You can use the root user to install the server or some other user with sudo rights. Once the RPM file has been transferred, install the server.</p>
<pre class="brush: bash; title: ; notranslate">
cd
sudo rpm -Uvh chef-server-core-12.17.15-1.el7.x86_64.rpm
</pre>
<p>Most likely, you&#8217;ll file-name will differ because Chef releases updates quite often.<br />
Once installed, do an initial configuration.</p>
<pre class="brush: bash; title: ; notranslate">
sudo chef-server-ctl reconfigure
</pre>
<p>We need to create an admin user for Chef. This admin users is a Chef user, not an OS user.</p>
<pre class="brush: bash; title: ; notranslate">
sudo chef-server-ctl user-create chef-admin Chef Admin chefadmin@iandreev.com SomePassword --filename chef-admin.pem
</pre>
<p>This command will create an admin user called <strong>chef-admin</strong> with first name <strong>Chef </strong>and last name <strong>Admin</strong>. The e-mail of the <strong>chef-admin</strong> user is <strong>chefadmin@iandreev.com</strong> and the password is <strong>SomePassword</strong>. The command will also create a certificate that we will use to log to the server from the workstation. So, the PEM file is very important. If everything is OK, you&#8217;ll get your prompt back without any notifications.<br />
Now that we have the user created, we&#8217;ll create an organization. An organization is a top-level entity for the roles, groups and nodes. With the same command, we&#8217;ll add the user that we just created as a member of the organization.</p>
<pre class="brush: bash; title: ; notranslate">
sudo chef-server-ctl org-create chef-org &quot;Chef Organization, Inc.&quot; --association_user chef-admin --filename chef-org.pem
</pre>
<p>This command creates a Chef organization called <strong>chef-org</strong>, a detailed description for the organization is &#8220;<strong>Chef Organization, Inc.</strong>&#8221; and we associate the user <strong>chef-admin</strong> with the organization. The PEM file is used for validation as well, but we won&#8217;t need it. It was used in versions of Chef before v12 to authenticate users. Make sure that the organization&#8217;s name is all lower case, otherwise you&#8217;ll get an error.<br />
At this point, we have the user and the organization created. This should be enough to do everything we need, but we&#8217;ll install a GUI called Chef Manage that can ease some of the admin tasks. </p>
<pre class="brush: bash; title: ; notranslate">
sudo chef-server-ctl install chef-manage 
</pre>
<p>Once installed, we have to accept the license. Type <strong>yes </strong>and hit Enter when prompted.</p>
<pre class="brush: bash; title: ; notranslate">
sudo chef-manage-ctl reconfigure
</pre>
<p>Once completed, you can access the server over https (e.g. https://chef_server_name_or_ip). Use the same username and password from the above. It looks like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/01/P096-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/01/P096-01.png" alt="" width="935" height="687" class="aligncenter size-full wp-image-7806" srcset="https://blog.andreev.it/wp-content/uploads/2018/01/P096-01.png 935w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-01-300x220.png 300w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-01-768x564.png 768w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-01-585x430.png 585w" sizes="(max-width: 935px) 100vw, 935px" /></a><br />
We are done with the server. </p>
<h1>Chef workstation</h1>
<p>Chef servers are managed from workstations. We&#8217;ll use Windows 10. The installation is very simple. Go to this <a href="https://downloads.chef.io/chefdk#windows" rel="noopener noreferrer" target="_blank">link </a>and download the client (Chef DK &#8211; Development Kit) for Windows 10. Use the defaults to install. Once installed, you&#8217;ll see a shortcut on your desktop. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2018/01/P096-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/01/P096-02.png" alt="" width="114" height="131" class="aligncenter size-full wp-image-7807" /></a><br />
This will start PowerShell in admin mode. If your workstation was never configured for PowerShell, you&#8217;ll see something like this. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2018/01/P096-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/01/P096-03.png" alt="" width="1200" height="221" class="aligncenter size-full wp-image-7808" srcset="https://blog.andreev.it/wp-content/uploads/2018/01/P096-03.png 1200w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-03-300x55.png 300w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-03-1024x189.png 1024w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-03-768x141.png 768w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-03-1170x215.png 1170w, https://blog.andreev.it/wp-content/uploads/2018/01/P096-03-585x108.png 585w" sizes="(max-width: 1200px) 100vw, 1200px" /></a><br />
Type:</p>
<pre class="brush: powershell; title: ; notranslate">
Set-ExecutionPolicy RemoteSigned
</pre>
<p>and say <strong>Y</strong> and enter.<br />
Close the window and open it again. This time you&#8217;ll be greeted with Ohai, welcome to ChefDK.<br />
OK, so now we have the client installed, but how do we talk to the server? We need some sort of a home folder where all of our cookbooks, recipes and config files will be stored. I&#8217;ll use a folder called <strong>chef </strong>that&#8217;s under the <strong>Documents </strong>folder for this.</p>
<pre class="brush: powershell; title: ; notranslate">
cd ~\Documents
mkdir -p chef\.chef
</pre>
<p>We created another subfolder <strong>.chef</strong>, where we&#8217;ll keep our certificate. That&#8217;s the certificate that we generated when we created the <strong>chef-admin</strong> user. Let&#8217;s copy that file from the server to the workstation. Mind that the user <strong>username </strong>in the command below is the user that I&#8217;ve used to run the Chef install. If you used <strong>root </strong>to install the Chef server, replace the <strong>username </strong>with <strong>root</strong>.</p>
<pre class="brush: powershell; title: ; notranslate">
scp username@chef-server:~username/chef-admin.pem chef/.chef/chef-admin.pem
</pre>
<p>This command will add the Chef server (<strong>hostname: chef-server</strong>) to the list of known hosts under <strong>C:\users\<your_username>\.ssh</strong> folder and copy the certificate PEM file under <strong>C:\users\<your_username>\Documents\chef\.chef</strong> folder. Let&#8217;s create a folder where we&#8217;ll store our cookbooks.</p>
<pre class="brush: powershell; title: ; notranslate">
cd ~\Documents\chef
mkdir cookbooks
</pre>
<p>Now, create a file called <strong>knife.rb</strong> with the following content and save it under <strong>chef\.chef</strong> folder. Or, if you have the <strong>Chef Manage GUI</strong>, you can download the same file if you go to <strong>Administration </strong>from the menu, then select your <strong>Organization </strong>and then <strong>Generate Knife Config</strong> from the left side-bar.</p>
<pre class="brush: ruby; title: ; notranslate">
current_dir = File.dirname(__FILE__)
log_level                 :info
log_location              STDOUT
node_name                 &quot;chef-admin&quot;
client_key                &quot;#{current_dir}/chef-admin.pem&quot;
chef_server_url           &quot;https://chef-server.chef.local/organizations/chef-org&quot;
cookbook_path             &#x5B;&quot;#{current_dir}/../cookbooks&quot;]
</pre>
<p>Under the <strong>chef\.chef</strong> folder, you should have two files now: <strong>chef-admin.pem</strong> certificate and <strong>knife.rb</strong> config file. Let&#8217;s verify if we are all set now.</p>
<pre class="brush: bash; title: ; notranslate">
cd ~\Documents\chef
knife ssl fetch
</pre>
<p>You should see something like this. This will import the nginx server certificate to your local cert store. </p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
WARNING: Certificates from chef-server.chef.local will be fetched and placed in your trusted_cert
directory (c:\users\kliment.andreev\documents\chef\.chef\trusted_certs).

Knife has no means to verify these are the correct certificates. You should
verify the authenticity of these certificates after downloading.

Adding certificate for chef-server_chef_local in c:\users\kliment.andreev\documents\chef\.chef\trusted_certs/chef-server_chef_local.crt
</pre>
<p>OK. Then, check.</p>
<pre class="brush: powershell; title: ; notranslate">
cd ~\Documents\chef
knife ssl check
</pre>
<p>It should say something like this.</p>
<pre class="brush: plain; title: ; notranslate">
Connecting to host chef-server.chef.local:443
Successfully verified certificates from `chef-server.chef.local'
</pre>
<p>This is also a good sign that everything works fine. Sometimes <strong>ssl fetch</strong> and <strong>ssl check pass</strong>, but this one fails. In that case, make sure that the <strong>node_name</strong> directive in <strong>knife.rb</strong> is your actual <strong>chef-admin</strong> name. </p>
<pre class="brush: powershell; title: ; notranslate">
cd ~\Documents\chef
knife client list
</pre>
<p>The output should be something like <strong>chef-org-validator</strong>. If you noticed, I used <strong>cd ~\Documents\chef</strong> a lot. Chef is kind of picky, so it is important to know where are you in the folder tree when running the commands. Always make sure you are in your home directory, <strong>cd ~\Documents\chef</strong> before running the <strong>knife </strong>and <strong>chef </strong>commands. </p>
<h1>Configure git</h1>
<p>Before we generate our first cookbook, we&#8217;ll have to configure git. Do that with the following commands.</p>
<pre class="brush: powershell; title: ; notranslate">
git config --global user.email &quot;you@example.com&quot;
git config --global user.name &quot;Your Name&quot;
</pre>
<h1>Test cookbook</h1>
<p>Without going into any explanations, we&#8217;ll create a test cookbook, upload it to the server and then list the server for available cookbooks.</p>
<pre class="brush: powershell; title: ; notranslate">
cd ~\Documents\chef
chef generate cookbook cookbooks/test
knife cookbook upload test
knife cookbook list
</pre>
<p>If the output looks like this, you are OK. </p>
<pre class="brush: plain; gutter: false; title: ; notranslate">
PS C:\Users\Kliment.ANDREEV\documents\chef&gt; chef generate cookbook cookbooks/test
Generating cookbook test
- Ensuring correct cookbook file content
- Committing cookbook files to git
- Ensuring delivery configuration
- Ensuring correct delivery build cookbook content
- Adding delivery configuration to feature branch
- Adding build cookbook to feature branch
- Merging delivery content feature branch to master

Your cookbook is ready. Type `cd cookbooks/test` to enter it.

There are several commands you can run to get started locally developing and testing your cookbook.
Type `delivery local --help` to see a full list.

Why not start by writing a test? Tests for the default recipe are stored at:

test/smoke/default/default_test.rb

If you'd prefer to dive right in, the default recipe can be found at:

recipes/default.rb

PS C:\Users\Kliment.ANDREEV\documents\chef&gt; knife cookbook upload test
Uploading test         &#x5B;0.1.0]
Uploaded 1 cookbook.

PS C:\Users\Kliment.ANDREEV\documents\chef&gt; knife cookbook list
test   0.1.0

PS C:\Users\Kliment.ANDREEV\documents\chef&gt;
</pre>
<h1>Chef node</h1>
<p>From the workstation execute this line to install the node.</p>
<pre class="brush: bash; title: ; notranslate">
knife bootstrap chef-node --ssh-user username --sudo -N chef-node.chef.local
</pre>
<p>Use a username that can <strong>su </strong>as root, otherwise the command will fail. You have to enter the password twice. Once for the username prompt and the second time for the sudo. The output should look like this. Click to expand.</p>
<pre class="brush: plain; collapse: true; light: false; title: ; toolbar: true; notranslate">
Creating new client for chef-node.chef.local
Creating new node for chef-node.chef.local
Connecting to chef-node
username@chef-node's password:
chef-node 
chef-node We trust you have received the usual lecture from the local System
chef-node Administrator. It usually boils down to these three things:
chef-node 
chef-node     #1) Respect the privacy of others.
chef-node     #2) Think before you type.
chef-node     #3) With great power comes great responsibility.
chef-node 
chef-node knife sudo password: 
Enter your password: 
chef-node 
chef-node -----&gt; Installing Chef Omnibus (-v 13)
chef-node downloading https://omnitruck-direct.chef.io/chef/install.sh
chef-node   to file /tmp/install.sh.2931/install.sh
chef-node trying wget...
chef-node el 7 x86_64
chef-node Getting information for chef stable 13 for el...
chef-node downloading https://omnitruck-direct.chef.io/stable/chef/metadata?v=13&amp;p=el&amp;pv=7&amp;m=x86_64
chef-node   to file /tmp/install.sh.2944/metadata.txt
chef-node trying wget...
chef-node sha1   037a61a5d9c89d9b71d4c4f6256f45ed422a73ee
chef-node sha256 18826690ac2c7e5f16a21d898ed77be7d78fd2d84bc2a71b4506ee480876bc4b
chef-node url    https://packages.chef.io/files/stable/chef/13.6.4/el/7/chef-13.6.4-1.el7.x86_64.rpm
chef-node version        13.6.4
chef-node downloaded metadata file looks valid...
chef-node downloading https://packages.chef.io/files/stable/chef/13.6.4/el/7/chef-13.6.4-1.el7.x86_64.rpm
chef-node   to file /tmp/install.sh.2944/chef-13.6.4-1.el7.x86_64.rpm
chef-node trying wget...
chef-node Comparing checksum with sha256sum...
chef-node Installing chef 13
chef-node installing with rpm...
chef-node warning: /tmp/install.sh.2944/chef-13.6.4-1.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
chef-node Preparing...                                                            (1################################# &#x5B;100%]
chef-node Updating / installing...
chef-node    1:chef-13.6.4-1.el7                                                  ( ################################# &#x5B;100%]
chef-node Thank you for installing Chef!
chef-node Starting the first Chef Client run...
chef-node Starting Chef Client, version 13.6.4
chef-node resolving cookbooks for run list: &#x5B;]
chef-node Synchronizing Cookbooks:
chef-node Installing Cookbook Gems:
chef-node Compiling Cookbooks...
chef-node &#x5B;2018-01-20T08:33:15-08:00] WARN: Node chef-node.chef.local has an empty run list.
chef-node Converging 0 resources
chef-node 
chef-node Running handlers:
chef-node Running handlers complete
chef-node Chef Client finished, 0/0 resources updated in 08 seconds
</pre>
<p>Windows requires port 5985 (WinRM) to be opened, so make sure you allow this port, especially if the Chef server and the Chef Windows node are not in the same domain. To test the connection, do:</p>
<pre class="brush: bash; title: ; notranslate">
knife wsman test chef-node-win --manual-list
</pre>
<p>The output should be like this. </p>
<pre class="brush: plain; title: ; notranslate">
Connected successfully to chef-node-win at http://node-win:5985/wsman.
</pre>
<p>For some reason, I wasn&#8217;t able to install Chef node on Windows using an admin account that I&#8217;ve created. I was getting authentication errors. Once I used the built-in Administrator account, everything went fine. This is how to install Chef on Windows.</p>
<pre class="brush: bash; title: ; notranslate">
knife bootstrap windows winrm chef-node-win.chef.local --winrm-user Administrator --winrm-password MyPassword -N node-win.chef.local
</pre>
<p>And if everything is OK, you&#8217;ll see the output. Click to expand.</p>
<pre class="brush: plain; collapse: true; light: false; title: ; toolbar: true; notranslate">
Creating new client for chef-node-win.chef.local
Creating new node for chef-node-win.chef.local

Waiting for remote response before bootstrap.chef-node-win.chef.local . 
chef-node-win.chef.local Response received.
Remote node responded after 0.0 minutes.
Bootstrapping Chef on chef-node-win.chef.local
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 1 
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 2 
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 3 
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 4 
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 5 
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 6 
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 7 
chef-node-win.chef.local Rendering &quot;C:\Users\ADMINI~1\AppData\Local\Temp\bootstrap-35815-1516539477.bat&quot; chunk 8 
chef-node-win.chef.local Checking for existing directory &quot;C:\chef&quot;...
chef-node-win.chef.local Existing directory not found, creating.
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;(
chef-node-win.chef.local echo.url = WScript.Arguments.Named(&quot;url&quot;)  
chef-node-win.chef.local  echo.path = WScript.Arguments.Named(&quot;path&quot;)  
chef-node-win.chef.local  echo.proxy = null  
chef-node-win.chef.local  echo.'* Vaguely attempt to handle file:// scheme urls by url unescaping and switching all  
chef-node-win.chef.local  echo.'* / into .  Also assume that file:/// is a local absolute path and that file://&lt;foo&gt;  
chef-node-win.chef.local  echo.'* is possibly a network file path.  
chef-node-win.chef.local  echo.If InStr(url, &quot;file://&quot;) = 1 Then  
chef-node-win.chef.local  echo.url = Unescape(url)  
chef-node-win.chef.local  echo.If InStr(url, &quot;file:///&quot;) = 1 Then  
chef-node-win.chef.local  echo.sourcePath = Mid(url, Len(&quot;file:///&quot;) + 1)  
chef-node-win.chef.local  echo.Else 
chef-node-win.chef.local  echo.sourcePath = Mid(url, Len(&quot;file:&quot;) + 1)  
chef-node-win.chef.local  echo.End If  
chef-node-win.chef.local  echo.sourcePath = Replace(sourcePath, &quot;/&quot;, &quot;\&quot;)  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.Set objFSO = CreateObject(&quot;Scripting.FileSystemObject&quot;)  
chef-node-win.chef.local  echo.If objFSO.Fileexists(path) Then objFSO.DeleteFile path  
chef-node-win.chef.local  echo.objFSO.CopyFile sourcePath, path, true  
chef-node-win.chef.local  echo.Set objFSO = Nothing  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.Else 
chef-node-win.chef.local  echo.Set objXMLHTTP = CreateObject(&quot;MSXML2.ServerXMLHTTP&quot;)  
chef-node-win.chef.local  echo.Set wshShell = CreateObject( &quot;WScript.Shell&quot; )  
chef-node-win.chef.local  echo.Set objUserVariables = wshShell.Environment(&quot;USER&quot;)  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.rem http proxy is optional  
chef-node-win.chef.local  echo.rem attempt to read from HTTP_PROXY env var first  
chef-node-win.chef.local  echo.On Error Resume Next  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.If NOT (objUserVariables(&quot;HTTP_PROXY&quot;) = &quot;&quot;) Then  
chef-node-win.chef.local  echo.proxy = objUserVariables(&quot;HTTP_PROXY&quot;)  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.rem fall back to named arg  
chef-node-win.chef.local  echo.ElseIf NOT (WScript.Arguments.Named(&quot;proxy&quot;) = &quot;&quot;) Then  
chef-node-win.chef.local  echo.proxy = WScript.Arguments.Named(&quot;proxy&quot;)  
chef-node-win.chef.local  echo.End If  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.If NOT isNull(proxy) Then  
chef-node-win.chef.local  echo.rem setProxy method is only available on ServerXMLHTTP 6.0+  
chef-node-win.chef.local  echo.Set objXMLHTTP = CreateObject(&quot;MSXML2.ServerXMLHTTP.6.0&quot;)  
chef-node-win.chef.local  echo.objXMLHTTP.setProxy 2, proxy  
chef-node-win.chef.local  echo.End If  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.On Error Goto 0  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.objXMLHTTP.open &quot;GET&quot;, url, false  
chef-node-win.chef.local  echo.objXMLHTTP.send() 
chef-node-win.chef.local  echo.If objXMLHTTP.Status = 200 Then  
chef-node-win.chef.local  echo.Set objADOStream = CreateObject(&quot;ADODB.Stream&quot;)  
chef-node-win.chef.local  echo.objADOStream.Open 
chef-node-win.chef.local  echo.objADOStream.Type = 1  
chef-node-win.chef.local  echo.objADOStream.Write objXMLHTTP.ResponseBody  
chef-node-win.chef.local  echo.objADOStream.Position = 0  
chef-node-win.chef.local  echo.Set objFSO = Createobject(&quot;Scripting.FileSystemObject&quot;)  
chef-node-win.chef.local  echo.If objFSO.Fileexists(path) Then objFSO.DeleteFile path  
chef-node-win.chef.local  echo.Set objFSO = Nothing  
chef-node-win.chef.local  echo.objADOStream.SaveToFile path  
chef-node-win.chef.local  echo.objADOStream.Close 
chef-node-win.chef.local  echo.Set objADOStream = Nothing  
chef-node-win.chef.local  echo.End If  
chef-node-win.chef.local  echo.Set objXMLHTTP = Nothing  
chef-node-win.chef.local  echo.End If 
chef-node-win.chef.local ) 1&gt;C:\chef\wget.vbs 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;(
chef-node-win.chef.local echo.param( 
chef-node-win.chef.local  echo.   &#x5B;String] $remoteUrl,  
chef-node-win.chef.local  echo.   &#x5B;String] $localPath  
chef-node-win.chef.local  echo.) 
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.$ProxyUrl = $env:http_proxy;  
chef-node-win.chef.local  echo.$webClient = new-object System.Net.WebClient;  
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.if ($ProxyUrl -ne '') {  
chef-node-win.chef.local  echo.  $WebProxy = New-Object System.Net.WebProxy($ProxyUrl,$true)  
chef-node-win.chef.local  echo.  $WebClient.Proxy = $WebProxy  
chef-node-win.chef.local  echo.} 
chef-node-win.chef.local  echo. 
chef-node-win.chef.local  echo.$webClient.DownloadFile($remoteUrl, $localPath); 
chef-node-win.chef.local ) 1&gt;C:\chef\wget.ps1 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;(
chef-node-win.chef.local  
chef-node-win.chef.local   
chef-node-win.chef.local  
chef-node-win.chef.local ) 
chef-node-win.chef.local Detected Windows Version 6.3 Build 9600
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;goto Version6.3 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;goto Version6.2 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;goto architecture_select 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;IF &quot;AMD64&quot; == &quot;x86&quot; IF not defined PROCESSOR_ARCHITEW6432 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;goto install 
chef-node-win.chef.local Checking for existing downloaded package at &quot;C:\Users\ADMINI~1\AppData\Local\Temp\chef-client-latest.msi&quot;
chef-node-win.chef.local No existing downloaded packages to delete.
chef-node-win.chef.local Attempting to download client package using PowerShell if available...
chef-node-win.chef.local powershell.exe -ExecutionPolicy Unrestricted -InputFormat None -NoProfile -NonInteractive -File  C:\chef\wget.ps1 &quot;https://www.chef.io/chef/download?p=windows&amp;pv=2012&amp;m=x86_64&amp;DownloadContext=PowerShell&amp;v=13&quot; &quot;C:\Users\ADMINI~1\AppData\Local\Temp\chef-client-latest.msi&quot;
chef-node-win.chef.local Download via PowerShell succeeded.
chef-node-win.chef.local Installing downloaded client package...
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;msiexec /qn /log &quot;C:\Users\ADMINI~1\AppData\Local\Temp\chef-client-msi20931.log&quot; /i &quot;C:\Users\ADMINI~1\AppData\Local\Temp\chef-client-latest.msi&quot; 
chef-node-win.chef.local Successfully installed Chef Client package.
chef-node-win.chef.local Installation completed successfully
chef-node-win.chef.local Writing validation key...
chef-node-win.chef.local Validation key written.
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;mkdir C:\chef\trusted_certs 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;(
chef-node-win.chef.local echo.-----BEGIN CERTIFICATE-----  
chef-node-win.chef.local  echo.MIID6zCCAtOgAwIBAgIBADANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJVUzEQ 
chef-node-win.chef.local  echo.MA4GA1UECgwHWW91Q29ycDETMBEGA1UECwwKT3BlcmF0aW9uczEbMBkGA1UEAwwS 
chef-node-win.chef.local  echo.Y2hlZi5hbmRyZWV2LmxvY2FsMB4XDTE4MDExNDIyMjkwMloXDTI4MDExMjIyMjkw 
chef-node-win.chef.local  echo.MlowUTELMAkGA1UEBhMCVVMxEDAOBgNVBAoMB1lvdUNvcnAxEzARBgNVBAsMCk9w 
chef-node-win.chef.local  echo.ZXJhdGlvbnMxGzAZBgNVBAMMEmNoZWYuYW5kcmVldi5sb2NhbDCCASIwDQYJKoZI 
chef-node-win.chef.local  echo.hvcNAQEBBQADggEPADCCAQoCggEBAKiyl7i+TpCdwvWtAnpcktKL5BKm/zonS87f 
chef-node-win.chef.local  echo.mm61beXd7CDJifcpllinq/b/96r6872odbmVYHZ3uwGhX3+95AlFOOZiM+Ze08Ds 
chef-node-win.chef.local  echo.574Rj53Xz+ASSCcZsbwdAPc//dBs67GndNjgH3iy2bAFxjOkPJJX9bBZoKhYEXRp 
chef-node-win.chef.local  echo.9xEdUEQwj3W0g92b3sDx2gDSOXgP43g+vqRLjUiCAmRmCmgFkMkb9Xitxn3CXXiM 
chef-node-win.chef.local  echo.KDSUDiR1CA8FbrzIZ/O4ahB9UMeGvUEUkD2nN3BcWphXYWz5sVxxVBlqmyK51EIa 
chef-node-win.chef.local  echo.lUd/lKw0xw2iYPUAkjxPdr7djJGgEQqXiYC3/r4v4w3RAdVY5jUCAwEAAaOBzTCB 
chef-node-win.chef.local  echo.yjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBT+SJ3clvJyuQqFPpcaCWX7QB8i 
chef-node-win.chef.local  echo.HzAdBgNVHREEFjAUghJjaGVmLmFuZHJlZXYubG9jYWwweQYDVR0jBHIwcIAU/kid 
chef-node-win.chef.local  echo.3JbycrkKhT6XGgll+0AfIh+hVaRTMFExCzAJBgNVBAYTAlVTMRAwDgYDVQQKDAdZ 
chef-node-win.chef.local  echo.b3VDb3JwMRMwEQYDVQQLDApPcGVyYXRpb25zMRswGQYDVQQDDBJjaGVmLmFuZHJl 
chef-node-win.chef.local  echo.ZXYubG9jYWyCAQAwDQYJKoZIhvcNAQELBQADggEBAImSEMXEX+rqbRd3ireoFbkY 
chef-node-win.chef.local  echo.b97RmbsXjcwmA6MuAIZIyoFw/DwRUBrahrlLhXEAgeDWPlgS2xGniLJxdGx5a0ca 
chef-node-win.chef.local  echo.pz/8hC4RQuIq4kOWhkvcFTms/hPXIVSyBcYEt4FFkrhOeIDxwoBrEfIFncXC8DiL 
chef-node-win.chef.local  echo.IdPUH1DZeJLx8T7zCrUjFpPG3IL65HXIsteXaGNsJtKoRdDprPIIGlUlw72n5M9Y 
chef-node-win.chef.local  echo.Y8VoH6s5roky3OemhOIqPzgK/fVhY3cQWivRdDNe7M2hT03TmwpvbFs0Emydaa+Q 
chef-node-win.chef.local  echo.E+QroZpUvQZK6I6gtN1kG5K8M+HBNnx2NavKj8YjuQokeJYEF6Fb7dhGz5BMgPU=  
chef-node-win.chef.local  echo.-----END CERTIFICATE----- 
chef-node-win.chef.local ) 1&gt;C:\chef/trusted_certs/chef_andreev_local.crt 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;(
chef-node-win.chef.local echo.chef_server_url  &quot;https://chef.andreev.local/organizations/iandreev&quot;  
chef-node-win.chef.local  echo.validation_client_name &quot;chef-validator&quot;  
chef-node-win.chef.local  echo.file_cache_path   &quot;c:/chef/cache&quot;  
chef-node-win.chef.local  echo.file_backup_path  &quot;c:/chef/backup&quot;  
chef-node-win.chef.local  echo.cache_options     ({:path =&gt; &quot;c:/chef/cache/checksums&quot;, :skip_expires =&gt; true})  
chef-node-win.chef.local  echo.node_name &quot;chef-node-win.chef.local&quot;  
chef-node-win.chef.local  echo.log_level        :info  
chef-node-win.chef.local  echo.log_location       STDOUT  
chef-node-win.chef.local  echo.trusted_certs_dir &quot;c:/chef/trusted_certs&quot; 
chef-node-win.chef.local ) 1&gt;C:\chef\client.rb 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;(echo.{&quot;run_list&quot;:&#x5B;]}) 1&gt;C:\chef\first-boot.json 
chef-node-win.chef.local Starting chef to bootstrap the node...
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;SET &quot;PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ruby\bin;C:\opscode\chef\bin;C:\opscode\chef\embedded\bin&quot; 
chef-node-win.chef.local 
chef-node-win.chef.local C:\Users\Administrator&gt;chef-client -c c:/chef/client.rb -j c:/chef/first-boot.json 
chef-node-win.chef.local Starting Chef Client, version 13.6.4
chef-node-win.chef.local 
chef-node-win.chef.local &#x5B;2018-01-21T07:58:38-05:00] INFO: *** Chef 13.6.4 ***
chef-node-win.chef.local &#x5B;2018-01-21T07:58:38-05:00] INFO: Platform: x64-mingw32
chef-node-win.chef.local &#x5B;2018-01-21T07:58:38-05:00] INFO: Chef-client pid: 2936
chef-node-win.chef.local &#x5B;2018-01-21T07:58:38-05:00] INFO: The plugin path C:\chef\ohai\plugins does not exist. Skipping...
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Setting the run_list to &#x5B;] from CLI options
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Run List is &#x5B;]
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Run List expands to &#x5B;]
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Starting Chef Run for chef-node-win.chef.local
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Running start handlers
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Start handlers complete.
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Error while reporting run start to Data Collector. URL: https://chef.andreev.local/organizations/iandreev/data-collector Exception: 404 -- 404 &quot;Not Found&quot;  (This is normal if you do not have Chef Automate)
chef-node-win.chef.local resolving cookbooks for run list: &#x5B;]
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] INFO: Loading cookbooks &#x5B;]
chef-node-win.chef.local Synchronizing Cookbooks:
chef-node-win.chef.local Installing Cookbook Gems:
chef-node-win.chef.local Compiling Cookbooks...
chef-node-win.chef.local &#x5B;2018-01-21T07:58:49-05:00] WARN: Node chef-node-win.chef.local has an empty run list.
chef-node-win.chef.local Converging 0 resources
chef-node-win.chef.local 
chef-node-win.chef.local &#x5B;2018-01-21T07:58:50-05:00] INFO: Chef Run complete in 0.437135 seconds
chef-node-win.chef.local 
chef-node-win.chef.local Running handlers:
chef-node-win.chef.local &#x5B;2018-01-21T07:58:50-05:00] INFO: Running report handlers
chef-node-win.chef.local Running handlers complete
chef-node-win.chef.local &#x5B;2018-01-21T07:58:50-05:00] INFO: Report handlers complete
chef-node-win.chef.local Chef Client finished, 0/0 resources updated in 11 seconds
</pre>
<p>Check the details for each node.</p>
<pre class="brush: bash; title: ; notranslate">
knife node show chef-node.chef.local
Node Name:   chef-node.chef.local
Environment: _default
FQDN:        chef-node.chef.local
IP:          192.168.1.16
Run List:    
Roles:       
Recipes:     
Platform:    centos 7.2.1511
Tags:    
</pre>
<pre class="brush: bash; title: ; notranslate">    
knife node show chef-node-win.chef.local
Node Name:   chef-node-win.chef.local
Environment: _default
FQDN:        chef-node-win
IP:          192.168.1.20
Run List:    
Roles:       
Recipes:     
Platform:    windows 6.3.9600
Tags:        
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2018/01/119-centos-chef-install-chef-server-centos-7-workstation-windows-managing-node/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>CentOS, FreeBSD, Windows: rsyslog server and client</title>
		<link>https://blog.andreev.it/2017/12/118-linux-freebsd-windows-rsyslog-server-client/</link>
					<comments>https://blog.andreev.it/2017/12/118-linux-freebsd-windows-rsyslog-server-client/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sun, 03 Dec 2017 23:56:22 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[rsyslog]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=3480</guid>

					<description><![CDATA[In this post, I&#8217;ll explain how to configure a rsyslog server and client on&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this post, I&#8217;ll explain how to configure a <strong>rsyslog </strong>server and client on various operating systems. For the servers, I&#8217;ll chose 2 Red Hat 7 servers and the clients will be AWS Linux, FreeBSD and Windows 2016.<br />
<strong>rsyslog </strong>is an open-source utility for logging, a derivate of the original syslog. As defined by <a href="https://tools.ietf.org/html/rfc3164" rel="noopener noreferrer" target="_blank">RFC 3164</a>, each message includes the facility code and severity level. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-01.png" alt="" width="450" height="690" class="aligncenter size-full wp-image-7794" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-01.png 450w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-01-196x300.png 196w" sizes="(max-width: 450px) 100vw, 450px" /></a><br />
The severity levels are these. (Both screenshots are from <a href="https://en.wikipedia.org/wiki/Syslog" rel="noopener noreferrer" target="_blank">Wikipedia</a>).<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-02.png" alt="" width="958" height="399" class="aligncenter size-full wp-image-7795" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-02.png 958w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-02-300x125.png 300w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-02-768x320.png 768w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-02-585x244.png 585w" sizes="(max-width: 958px) 100vw, 958px" /></a></p>
<h1>RHEL 7 rsyslog servers</h1>
<p>RHEL 7 comes with <strong>rsyslog </strong>installed by default. Make sure it&#8217;s running.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl status rsyslog
</pre>
<p>The configuration file is <strong>/etc/rsyslog.conf</strong>. Make sure that these lines are uncommented. They tell the <strong>rsyslog </strong>daemon to accept TCP and UDP connections.</p>
<pre class="brush: bash; title: ; notranslate">
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514

# Provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
</pre>
<p>If you make changes in <strong>/etc/rsyslog.conf</strong>, make sure you verify the config.</p>
<pre class="brush: bash; title: ; notranslate">
rsyslogd -N 1
</pre>
<p>If you make a change, you&#8217;ll have to restart the <strong>rsyslog </strong>daemon.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart rsyslog
</pre>
<p>To test if <strong>rsyslog </strong>works fine, try a test.</p>
<pre class="brush: bash; title: ; notranslate">
logger -p local0.notice -t from_cmd_line &quot;Test Message&quot;
</pre>
<p>If you check the <strong>/var/log/messages</strong>, a file where by default <strong>rsyslog </strong>writes the output, you&#8217;ll see the message.</p>
<pre class="brush: bash; title: ; notranslate">
tail /var/log/messages
</pre>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-03.png" alt="" width="562" height="48" class="aligncenter size-full wp-image-7796" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-03.png 562w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-03-300x26.png 300w" sizes="(max-width: 562px) 100vw, 562px" /></a><br />
OK, so we didn&#8217;t have to make any changes on both RHEL servers. Let&#8217;s move to the clients.<br />
NOTE: If you have firewalld enabled, you&#8217;ll have to open the ports for the clients.</p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --permanent --zone=public --add-port=514/tcp
firewall-cmd --permanent --zone=public --add-port=514/udp
firewall-cmd --reload
</pre>
<h1>AWS Linux, RHEL 6, CentOS 6</h1>
<p>AWS Linux is based on RHEL 6 so the instructions will apply for all of them. Check if <strong>rsyslog </strong>is running.</p>
<pre class="brush: bash; title: ; notranslate">
service rsyslog status
</pre>
<p>Edit <strong>/etc/rsyslog.conf</strong> and make sure these lines are commented. We don&#8217;t want a server, we want a client. </p>
<pre class="brush: bash; title: ; notranslate">
# Provides UDP syslog reception
#$ModLoad imudp
#$UDPServerRun 514

# Provides TCP syslog reception
#$ModLoad imtcp
#$InputTCPServerRun 514
</pre>
<p>Add these lines (11 to 14) somewhere at the end.</p>
<pre class="brush: bash; highlight: [11,12,13,14]; title: ; notranslate">
#$WorkDirectory /var/lib/rsyslog # where to place spool files
#$ActionQueueFileName fwdRule1 # unique name prefix for spool files
#$ActionQueueMaxDiskSpace 1g   # 1gb space limit (use as much as possible)
#$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
#$ActionQueueType LinkedList   # run asynchronously
#$ActionResumeRetryCount -1    # infinite retries if host is down
# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
#*.* @@remote-host:514
# ### end of the forwarding rule ###

*.*     @@10.0.0.170
$ActionExecOnlyWhenPreviousIsSuspended on
&amp; @@10.0.0.225
$ActionExecOnlyWhenPreviousIsSuspended off

# Finally include all config files in /etc/rsyslog.d. This allows overrides
# of the default configuration above.
$IncludeConfig /etc/rsyslog.d/*.conf
</pre>
<p>These four lines means that my primary <strong>rsyslog </strong>server has an IP of <strong>10.0.0.170</strong> and in case it&#8217;s not reachable, use the server <strong>10.0.0.225</strong>. Line 11 tells the <strong>rsyslog </strong>client to log everything to the server. If you want only certain messages logged, than you can change it, e.g. instead of <strong>*.* @@10.0.0.170</strong> you can use something like <strong>*.info @@10.0.0.170</strong> or <strong>*.info;auth.err @@10.0.0.170</strong>. Look at those two tables above. If you run this command on the client.</p>
<pre class="brush: bash; title: ; notranslate">
logger -p local0.notice -t from_aws_linux &quot;Test Message&quot;
</pre>
<p>and do</p>
<pre class="brush: bash; title: ; notranslate">
tail -f /var/log/messages
</pre>
<p>on the server, you&#8217;ll see the message on the server, not on the client.</p>
<h1>FreeBSD</h1>
<p>FreeBSD uses the old <strong>syslog</strong>, not <strong>rsyslog</strong>, but we can still redirect the logs to our RHEL servers. Edit <strong>/etc/syslog.conf</strong> and all the way at the end add this line.</p>
<pre class="brush: bash; title: ; notranslate">
*.* @10.0.0.170
</pre>
<p>As you can see, <strong>syslog </strong>uses one @, not two @@s. Restart the service and send a test message. You&#8217;ll see that the message goes to the RHEL server now.</p>
<pre class="brush: bash; title: ; notranslate">
service syslogd restart
logger -p local0.notice -t from_FreeBSD &quot;Test Message&quot;
</pre>
<h1>Windows</h1>
<p>Go to this <a href="http://www.rsyslog.com/windows-agent/" rel="noopener noreferrer" target="_blank">link </a>and download the rsyslog client. You can see the link for the download and also for the manual.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-04.png" alt="" width="724" height="290" class="aligncenter size-full wp-image-7797" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-04.png 724w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-04-300x120.png 300w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-04-585x234.png 585w" sizes="(max-width: 724px) 100vw, 724px" /></a><br />
The <strong>rsyslog </strong>agent for Windows is very detailed and requires some studying. Use the manual, there are some examples there. I&#8217;ll show you how to forward the <strong>event ID 7036</strong>. This event gets triggered when a service changes its state. So, download the client and open up the GUI. Expand the following and click on <strong>Rsyslog</strong>. Enter the primary and secondary rsyslog server&#8217;s IPs. Click <strong>Save </strong>in the upper left corner and then click <strong>Restart</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-05.png" alt="" width="990" height="646" class="aligncenter size-full wp-image-7798" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-05.png 990w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-05-300x196.png 300w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-05-768x501.png 768w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-05-585x382.png 585w" sizes="(max-width: 990px) 100vw, 990px" /></a><br />
If you check the logs on your rsyslog server, you&#8217;ll see a lot of logging going on. Pretty much everything that Windows does. We just want to filter all these logs to a single event ID.<br />
So, in the <strong>Default Rule Set</strong>, click <strong>Filters</strong>, then right-click <strong>AND</strong>, choose <strong>Add Filter, Event Log Monitor</strong> and then <strong>Event ID</strong>. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-06.png" alt="" width="910" height="556" class="aligncenter size-full wp-image-7799" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-06.png 910w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-06-300x183.png 300w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-06-768x469.png 768w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-06-585x357.png 585w" sizes="(max-width: 910px) 100vw, 910px" /></a><br />
Enter the Event ID <strong>7036</strong>, click <strong>Save </strong>and <strong>Restart</strong>. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-07.png" alt="" width="351" height="470" class="aligncenter size-full wp-image-7800" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-07.png 351w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-07-224x300.png 224w" sizes="(max-width: 351px) 100vw, 351px" /></a><br />
Now, go to <strong>Services </strong>(services.msc) and restart <strong>Windows Update </strong>service. You should see this on the rsyslog server.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/12/P095-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P095-08.png" alt="" width="565" height="75" class="aligncenter size-full wp-image-7801" srcset="https://blog.andreev.it/wp-content/uploads/2017/12/P095-08.png 565w, https://blog.andreev.it/wp-content/uploads/2017/12/P095-08-300x40.png 300w" sizes="(max-width: 565px) 100vw, 565px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2017/12/118-linux-freebsd-windows-rsyslog-server-client/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Windows: Enterprise PKI on Windows 2016</title>
		<link>https://blog.andreev.it/2017/12/117-windows-enterprise-pki-windows-2016/</link>
					<comments>https://blog.andreev.it/2017/12/117-windows-enterprise-pki-windows-2016/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sat, 02 Dec 2017 23:44:23 +0000</pubDate>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[Certificates]]></category>
		<category><![CDATA[Enterprise PKI]]></category>
		<category><![CDATA[PKI]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=3334</guid>

					<description><![CDATA[A public key infrastructure (PKI) is a set of roles, policies, and procedures needed&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>A public key infrastructure (PKI) is a set of roles, policies, and procedures needed to create, manage, distribute, use, store, and revoke digital certificates and manage public-key encryption. That&#8217;s what <a href="https://en.wikipedia.org/wiki/Public_key_infrastructure" rel="noopener noreferrer" target="_blank">Wikipedia </a>says.<br />
Today, using certificates is a must. Google search gives you better search scores if your web site is using certificates and if your site is mobile-friendly. So, in this post I’ll describe how to deploy an Enterprise PKI on Windows 2016 server. This post is mostly for on-prem deployments, but it will give you some insights on how PKI works. I will create one Windows IIS web server joined to the domain and one Linux server (not joined to the domain) running Apache. I&#8217;ll create SSL sites on both and deploy the certificates, so the clients (Windows machines on your corp domain) won&#8217;t get that certificate warning when browsing these site.<br />
In order to do what we planed, we’ll use Active Directory Certificate Services (AD CS). We’ll create a lab with a domain controller, an offline Certificate Authority, an Enterprise Certificate Authority and two web servers. These two web servers (one running IIS and the other running Apache) will host two web sites (test1 and test2) that will have SSL certificates issued by our CA.<br />
The hostnames are :</p>
<ul>
<li>dc01.empire.local</li>
<li>offCA</li>
<li>entCA.empire.local</li>
<li>iis.empire.local</li>
<li>apache</li>
</ul>
<div style="border:1px solid red; padding:16px;">
<p style="text-align:center;"><strong><span style="color:#800000;">NOTE</span> </strong></p>
<p style="text-align:center;"><em><strong>In this post, I&#8217;ll refer offline CA as Root CA and Enterprise CA as Subordinate CA.</strong></a></em><a href="http://paul-barford.blogspot.com/"> </a></p>
</div>
<h1>Domain Controller(s)</h1>
<p>I won’t explain how to create a domain controller. Just make sure you have a domain controller(s) in your environment. My domain is called <strong>empire.local</strong> with <strong>EMPIRE</strong> as a NetBIOS domain name.</p>
<h1>Offline Root Certificate Authority</h1>
<p>Why do we need an offline Certificate Authority and enterprise CA? It’s per MS best practices. The offline CA will be the one that holds the PKI, but once it’s configured it can be brought offline. The actual certificates will be signed by the enterprise CA. In case the enterprise CA gets compromised, you’ll have to bring the offlince CA on-line and revoke the certificate for the enterprise CA.<br />
So, let’s build the offline CA. This server shouldn’t be part of the domain. Leave it as a workgroup member. From the <strong>Server Manager</strong>, click on <strong>Add Roles and Features</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-01.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-3338" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-01.png" alt="" width="357" height="231" /></a><br />
Select <strong>Active Directory Certificate Services</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-02.png" alt="" width="787" height="558" class="aligncenter size-full wp-image-3344" /></a><br />
Under role services, select <strong>Certification Authority</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-03.png" alt="" width="780" height="563" class="aligncenter size-full wp-image-3345" /></a><br />
Once the installation is completed, click on the flag icon in the upper right corner to configure the CA.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-04.png" alt="" width="419" height="200" class="aligncenter size-full wp-image-3346" /></a><br />
Choose the defaults or if you want a separate local user, specify it here. You have to create that user first.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-05.png" alt="" width="757" height="557" class="aligncenter size-full wp-image-3347" /></a><br />
Choose to configure <strong>Certification Authority</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-06.png" alt="" width="763" height="560" class="aligncenter size-full wp-image-3348" /></a><br />
Choose <strong>Standalone CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-07.png" alt="" width="761" height="559" class="aligncenter size-full wp-image-3349" /></a><br />
Choose <strong>Root CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-08.png" alt="" width="749" height="557" class="aligncenter size-full wp-image-3350" /></a><br />
Select to <strong>Create a new private key</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-09.png" alt="" width="758" height="555" class="aligncenter size-full wp-image-3351" /></a><br />
Choose <strong>SHA256 </strong>and <strong>2048</strong>. Don’t use SHA1, it’s being deprecated.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-10.png" alt="" width="758" height="557" class="aligncenter size-full wp-image-3352" /></a><br />
Choose the common name for the CA. In my case it’s <strong>ROOT-CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-11.png" alt="" width="756" height="560" class="aligncenter size-full wp-image-3353" /></a><br />
Use validity for this CA. I used 10 instead of the default 5.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-12.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-12.png" alt="" width="758" height="559" class="aligncenter size-full wp-image-3354" /></a><br />
Choose where the database and the logs will be located. I used the defaults, best practice is to use a separate data drive.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-13.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-13.png" alt="" width="757" height="559" class="aligncenter size-full wp-image-3355" /></a><br />
Verify everything looks good and click <strong>Configure</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-14.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-14.png" alt="" width="764" height="554" class="aligncenter size-full wp-image-3356" /></a><br />
Once completed, go to <strong>C:\Windows\System32\CertSrv\CertEnroll</strong>. This is where you’ll have the root certificate (<strong>offCA_ROOT-CA.crt</strong>) and the Certificate Revocation List (<strong>ROOT-CA.crl</strong>).<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-15.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-15.png" alt="" width="718" height="203" class="aligncenter size-full wp-image-3357" /></a><br />
Go to the <strong>Administrative Tools</strong> under <strong>Control Panel</strong> and run the <strong>Certification Authority</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-16.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-16.png" alt="" width="544" height="198" class="aligncenter size-full wp-image-3358" /></a><br />
Now, we have to configure the Root (offline) CA so it is aware of the <strong>subordinate (enterprise) CA</strong>. Right click the name of the CA, choose <strong>Properties</strong> and then click on the <strong>Extensions</strong> tab. You’ll see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-17.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-17.png" alt="" width="602" height="628" class="aligncenter size-full wp-image-3359" /></a><br />
Click <strong>Add </strong>and enter the following in the <strong>Location</strong> field. Then click <strong>OK</strong>. Don’t click <strong>Insert</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
http://entCA.empire.local/certdata/&lt;CaName&gt;&lt;CRLNameSuffix&gt;&lt;DeltaCRLAllowed&gt;.crl
</pre>
<p>Replace <strong>entCA.empire.local</strong> with the name of your subordinate (enterprise) server.<br />
After you click <strong>OK</strong>, check these two checkmarks.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-18.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-18.png" alt="" width="397" height="535" class="aligncenter size-full wp-image-3369" /></a><br />
By default, they are not checked. Click <strong>Apply </strong>and you’ll be prompted to restart the CA service. Go back to the properties of the <strong>Root CA</strong>, click on the <strong>Extensions </strong>tab, but this time switch to <strong>Authority Information Access (AIA)</strong> instead of <strong>CRL Distribution Point (CDP)</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-19.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-19.png" alt="" width="414" height="541" class="aligncenter size-full wp-image-3362" /></a><br />
Same thing here. Click <strong>Add </strong>and enter the following in the <strong>Location </strong>field. </p>
<pre class="brush: bash; title: ; notranslate">
http://entCA.empire.local/certdata/&lt;ServerDNSName&gt;&lt;CaName&gt;&lt;CertificateName&gt;.crt
</pre>
<p>Replace <strong>entCA.empire.local</strong> with your enterprise CA server name.  Click <strong>OK</strong>, don’t click <strong>Insert</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-20.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-20.png" alt="" width="456" height="322" class="aligncenter size-full wp-image-3363" /></a><br />
Then check <strong>Include in the AIA extension of issues certificates</strong> which by default is not checked. Click <strong>OK </strong>and that will restart the CA service.<br />
Select <strong>Revoked Certiicates</strong>, right-click, choose <strong>All Tasks</strong> and then <strong>Publish</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-21.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-21.png" alt="" width="444" height="274" class="aligncenter size-full wp-image-3365" /></a><br />
Click <strong>OK</strong> for the <strong>New CRL</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-22.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-22.png" alt="" width="405" height="537" class="aligncenter size-full wp-image-3366" /></a><br />
If you go back to<strong> C:\Windows\System32\CertSrv\CertEnroll</strong>, you’ll see that the time stamp on <strong>ROOT-CA.crl</strong> file has changed.<br />
Now, we need the root certificate (without the private key) exported so we can copy it to the <strong>enterprise CA</strong>. Right-click the CA, choose <strong>Properties </strong>and from the <strong>General </strong>tab, choose <strong>View Certificate</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-23.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-23.png" alt="" width="442" height="619" class="aligncenter size-full wp-image-3367" /></a><br />
Click on <strong>Details </strong>tab and then <strong>Copy to File</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-24.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-24.png" alt="" width="442" height="619" class="aligncenter size-full wp-image-3373" /></a><br />
In the <strong>Certificate Export Wizard</strong>, choose the first option (<strong>DER</strong>).<br />
Click <strong>Next </strong>and save it under <strong>c:\windows\system32\certsrv\certenroll</strong> with a name something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-25.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-25.png" alt="" width="542" height="528" class="aligncenter size-full wp-image-3374" /></a><br />
Click <strong>Save </strong>then <strong>Finish</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-26.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-26.png" alt="" width="636" height="527" class="aligncenter size-full wp-image-3375" /></a><br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-27.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-27.png" alt="" width="531" height="518" class="aligncenter size-full wp-image-3378" /></a></p>
<h1>Enterprise (standalone) Certificate Authority</h1>
<p>Now, let’s move to the subordinate (enterprise) CA. This is the server that will actually issue and revoke certificates. Make sure this server is a member of the domain.<br />
From the server manager go to<strong> Add Roles and Features</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-28.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-28.png" alt="" width="357" height="231" class="aligncenter size-full wp-image-3377" /></a><br />
Choose <strong>Active Directory Certificate Services</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-29.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-29.png" alt="" width="780" height="558" class="aligncenter size-full wp-image-3379" /></a><br />
Choose both, <strong>Certification Authority</strong> and <strong>Certificate Authority Web Enrollment</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-30.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-30.png" alt="" width="775" height="557" class="aligncenter size-full wp-image-3380" /></a><br />
Web enrollment will require IIS. Choose defaults.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-31.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-31.png" alt="" width="788" height="559" class="aligncenter size-full wp-image-3381" /></a><br />
Once the installation is completed, click on the flag icon in the upper right corner to configure the CA.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-32.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-32.png" alt="" width="419" height="200" class="aligncenter size-full wp-image-3382" /></a><br />
Choose the Administrator or some other domain user if you want.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-33.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-33.png" alt="" width="766" height="556" class="aligncenter size-full wp-image-3383" /></a><br />
Select the <strong>Certification Authority</strong> and <strong>Certification Authority Web Enrollment</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-34.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-34.png" alt="" width="763" height="571" class="aligncenter size-full wp-image-3420" /></a><br />
Select <strong>Enterprise CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-35.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-35.png" alt="" width="752" height="555" class="aligncenter size-full wp-image-3385" /></a><br />
Select <strong>Subordinate CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-36.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-36.png" alt="" width="755" height="551" class="aligncenter size-full wp-image-3386" /></a><br />
<strong>Create a new Private key</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-37.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-37.png" alt="" width="749" height="554" class="aligncenter size-full wp-image-3387" /></a><br />
Choose <strong>SHA256 </strong>and <strong>2048</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-38.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-38.png" alt="" width="757" height="558" class="aligncenter size-full wp-image-3388" /></a><br />
Choose the common name. In my case it&#8217;s <strong>ENT-CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-39.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-39.png" alt="" width="754" height="555" class="aligncenter size-full wp-image-3389" /></a><br />
Choose where to save the request file. This will have to be signed by the <strong>Root CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-40.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-40.png" alt="" width="759" height="560" class="aligncenter size-full wp-image-3390" /></a><br />
Choose defaults. Again, best practice is to save it to a separate data drive.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-41.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-41.png" alt="" width="760" height="560" class="aligncenter size-full wp-image-3391" /></a><br />
Verify and click <strong>Configure</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-42.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-42.png" alt="" width="758" height="557" class="aligncenter size-full wp-image-3392" /></a><br />
You’ll see this warning. This means you have to sign the request file that we just saved under C:\<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-43.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-43.png" alt="" width="752" height="557" class="aligncenter size-full wp-image-3393" /></a><br />
Now, copy the files from the <strong>Root CA</strong> (the first server) to <strong>Enterprise CA</strong> (this server). You will need to copy those three files under <strong>C:\Windows\System32\CertSrv\CertEnroll</strong> to anywhere on the Enterprise CA server. Choose the desktop, we won’t need them after the configuration. Right click on the certificate file that we created (the one with <strong>NO-PVT-KEY</strong> in its name) in its name and a <strong>.cer</strong> as a file extenstion. Click on <strong>Install Certificate</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-44.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-44.png" alt="" width="529" height="275" class="aligncenter size-full wp-image-3394" /></a><br />
Choose <strong>Local Machine</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-45.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-45.png" alt="" width="530" height="523" class="aligncenter size-full wp-image-3395" /></a><br />
Choose <strong>Place all certificates in the following store</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-46.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-46.png" alt="" width="531" height="529" class="aligncenter size-full wp-image-3396" /></a><br />
Click <strong>Browse </strong>and select <strong>Trusted Root Certification Authority</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-47.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-47.png" alt="" width="537" height="527" class="aligncenter size-full wp-image-3397" /></a><br />
Click <strong>Next </strong>and <strong>Finish</strong>.<br />
Now, go to <strong>c:\inetpub\wwwroot\</strong> and create a folder <strong>certdata</strong>. Remember when we created the CDP and IAI extensions? We used something like <em>http://entCA.empire.local/certdata&#8230;</em> Well, we are creating that now. So, create that folder and move the other two files there.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-48.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-48.png" alt="" width="819" height="565" class="aligncenter size-full wp-image-3398" /></a><br />
OK, now go back to the offline <strong>Root CA</strong>. Copy the request file that was created when we installed CA on the <strong>Enterprise CA</strong>. That’s the file that’s on the C:\ drive of the <strong>Enterprise CA</strong>. Move it to the desktop of the <strong>offline Root CA</strong>.<br />
Launch the <strong>Certification Authority (Control Panel, Administrative Tools, Certification Authority) </strong>and select the name of the <strong>Root CA</strong>. Right-click, select <strong>All Tasks</strong> and then <strong>Submit New Request</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-49.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-49.png" alt="" width="451" height="289" class="aligncenter size-full wp-image-3399" /></a><br />
Browse to the file that we just copied on the desktop.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-50.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-50.png" alt="" width="661" height="558" class="aligncenter size-full wp-image-3400" /></a><br />
Click on <strong>Pending Requests</strong>. You’ll see our request is waiting for approval.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-51.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-51.png" alt="" width="774" height="306" class="aligncenter size-full wp-image-3401" /></a><br />
Select the requested item on the right and then right-click, <strong>All Tasks</strong> and <strong>Issue</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-52.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-52.png" alt="" width="752" height="320" class="aligncenter size-full wp-image-3402" /></a><br />
The request entry will be gone, but if you click on <strong>Issued Certificates</strong>, you’ll see the certificate there.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-53.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-53.png" alt="" width="783" height="239" class="aligncenter size-full wp-image-3403" /></a><br />
Double-click the certificate on the right and then click on <strong>Details </strong>tab.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-54.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-54.png" alt="" width="681" height="658" class="aligncenter size-full wp-image-3404" /></a><br />
Click <strong>Copy to File</strong>. In the export wizard choose this option.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-55.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-55.png" alt="" width="741" height="677" class="aligncenter size-full wp-image-3405" /></a><br />
Save it on the desktop. I named it as <strong>entCA-signed</strong>, which will remind me that this is a signed certificate for the Enterprise CA.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-56.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-56.png" alt="" width="741" height="683" class="aligncenter size-full wp-image-3406" /></a><br />
Go back to the <strong>Enterprise CA</strong> and copy this <strong>entCA-signed</strong> file to the desktop. Then start the <strong>Certification Authority (Control Panel, Administrative Tools, Certification Authority)</strong>. You will see that the CA service is stopped. Right click the enterprise CA name, choose <strong>All Tasks</strong> and then <strong>Install CA Certificate</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-57.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-57.png" alt="" width="537" height="339" class="aligncenter size-full wp-image-3407" /></a><br />
Browse to that file <strong>entCA-signed </strong>that we just copied from the <strong>offline Root CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-58.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-58.png" alt="" width="775" height="665" class="aligncenter size-full wp-image-3408" /></a><br />
Once imported, start the service from the toolbar (green triangle icon). The service should start successfully.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-59.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-59.png" alt="" width="604" height="291" class="aligncenter size-full wp-image-3409" /></a><br />
At this point we have to tell the domain controller that there is a new <strong>Enterprise CA</strong> in the environment. Log to the domain controller, and copy the file (ROOT-CERT-NO-PVT-KEY) from the <strong>Enterprise CA</strong>. I saved this file on the desktop on <strong>Enterprise CA</strong>, so do the same. Copy the file from the desktop of <strong>Enterprise CA</strong> to the desktop of the domain controller. On the domain controller, go to <strong>Control Panel</strong>, <strong>Administrative Tools</strong>, then <strong>Group Policy Management</strong>.<br />
Expand the GP to edit the default domain policy.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-60.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-60.png" alt="" width="747" height="549" class="aligncenter size-full wp-image-3410" /></a><br />
Right-click and <strong>Edit</strong>. Go to <strong>Computer Configuration</strong>, <strong>Policies</strong>, <strong>Windows Settings</strong>, <strong>Security Settings</strong>, <strong>Public Key Policies</strong> and <strong>Trusted Root Certification Authorities</strong>. Right click on it and choose <strong>Import</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-61.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-61.png" alt="" width="527" height="249" class="aligncenter size-full wp-image-3411" /></a><br />
Local machine is automatically selected.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-62.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-62.png" alt="" width="539" height="531" class="aligncenter size-full wp-image-3412" /></a><br />
Choose the certificate, the one without private key.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-63.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-63.png" alt="" width="625" height="508" class="aligncenter size-full wp-image-3413" /></a><br />
The <strong>Certificate Import Wizard</strong> will launch.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-64.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-64.png" alt="" width="540" height="524" class="aligncenter size-full wp-image-3414" /></a><br />
Make sure this is where the certificate will be stored.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-65.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-65.png" alt="" width="540" height="524" class="aligncenter size-full wp-image-3415" /></a><br />
Click <strong>Finish</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-66.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-66.png" alt="" width="537" height="519" class="aligncenter size-full wp-image-3416" /></a><br />
OK, what now? First, delete the files that you don’t need. The ones on the desktop of the <strong>Enterprise CA,</strong> the domain controller and the <strong>offline CA</strong>. and the request file on the c:\drive on the <strong>Enterprise CA</strong>. You can also shut down offline CA. it’s not needed for another 10 years.  </p>
<h1>IIS Windows Web Server</h1>
<p>OK, so we have the PKI in place, but let&#8217;s build an IIS web server that uses certificates, which means it will listen on port 443. This web server will be a member of a domain and the URL will be <strong>test1.empire.local</strong>. Users will access the site as https://site1.empire.local.<br />
Log in to the IIS server and install IIS. This server must be a member of the domain. From the <strong>Server Manager</strong> add the <strong>IIS </strong>role.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-67.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-67.png" alt="" width="771" height="563" class="aligncenter size-full wp-image-3430" /></a><br />
Create a folder called <strong>test1.empire.local</strong> under <strong>c:\inetpub\wwwroot</strong>. Create a text file called <strong>index.txt</strong> and type something.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-68.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-68.png" alt="" width="570" height="303" class="aligncenter size-full wp-image-3431" /></a><br />
Rename the <strong>index.txt</strong> as <strong>index.html</strong>.<br />
Start the <strong>Internet Information Services (IIS) Manager</strong> from <strong>Control Panel</strong>, <strong>Administrative Tools</strong> or click on Start then type <strong>inetmgr</strong>. Right-click on <strong>Sites </strong>and choose <strong>Add Website</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-69.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-69.png" alt="" width="355" height="314" class="aligncenter size-full wp-image-3432" /></a><br />
Configure it and click <strong>OK</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-70.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-70.png" alt="" width="589" height="572" class="aligncenter size-full wp-image-3433" /></a><br />
Once the site is started, make sure that you have the <strong>test1.empire.local</strong> in the DNS, so the client computers know that test1.empire.local resolves to an IP.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-71.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-71.png" alt="" width="1002" height="207" class="aligncenter size-full wp-image-3434" /></a><br />
From any machine that’s on the domain, go to http://test1.empire.local. Make sure it works.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-72.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-72.png" alt="" width="686" height="243" class="aligncenter size-full wp-image-3435" /></a><br />
Go back to the IIS server. Click on the IIS server name and double-click <strong>Server Certificates</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-73.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-73.png" alt="" width="563" height="440" class="aligncenter size-full wp-image-3436" /></a><br />
Click on <strong>Create Domain Certificate</strong> on the right side.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-79.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-79.png" alt="" width="296" height="279" class="aligncenter size-full wp-image-3438" /></a><br />
In the dialog box that shows up, fill out the values. The common name is the actual server name.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-74.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-74.png" alt="" width="668" height="515" class="aligncenter size-full wp-image-3439" /></a><br />
Click the <strong>Select </strong>button and specify our Enterprise CA. If you don&#8217;t see anything in the certification Authority box when you click Select, it means that the IIS server doesn&#8217;t know about the Enterprise CA because the default domain policy is not present. Try with <strong>gpforce /update</strong> first, to update the domain policy.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-75.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-75.png" alt="" width="667" height="520" class="aligncenter size-full wp-image-3442" /></a><br />
Click <strong>Finish</strong>.<br />
If everything goes according to the plan, you&#8217;ll see that you have your certificate issued.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-80.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-80.png" alt="" width="885" height="156" class="aligncenter size-full wp-image-3444" /></a><br />
Now, click on the actual web site that we created and click on <strong>Bindings </strong>on the right-side.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-76.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-76.png" alt="" width="908" height="422" class="aligncenter size-full wp-image-3445" /></a><br />
Click on <strong>Add </strong>button and fill out the values. Pretty much we are telling <strong>IIS </strong>that we want an SSL site that runs on port 443 with a certificate that we already got from the <strong>Enterprise CA</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-77.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-77.png" alt="" width="618" height="471" class="aligncenter size-full wp-image-3446" /></a><br />
Now, go back to any client on the network and browse to https://test1.empire.local. You&#8217;ll see this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-78.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-78.png" alt="" width="675" height="290" class="aligncenter size-full wp-image-3447" /></a><br />
If you click on the lock icon in the address bar, you&#8217;ll see that we got the certificates right.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-81.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-81.png" alt="" width="355" height="247" class="aligncenter size-full wp-image-3448" /></a></p>
<h1>Apache Web Server</h1>
<p>I&#8217;ll build a web server running Apache in the environment. I won&#8217;t go into details how to do that. Each flavor of Linux/*BSD has its own way of doing it. I&#8217;ll use AWS Linux which is based on Red Hat 6. It really doesn&#8217;t matter what you use, as long as you know how to configure Apache. Make sure you have the URL in the DNS, e.g. test2.empire.local to resolve to some IP.<br />
For instructions on how to configure Apache on AWS/RHEL6/CentOS 6, you can check my <a href="https://blog.andreev.it/?p=1010" rel="noopener noreferrer" target="_blank">post</a>. For RHEL 7/CentOS chek this <a href="https://blog.andreev.it/?p=1962" rel="noopener noreferrer" target="_blank">link </a>and for FreeBSD use this <a href="https://blog.andreev.it/?p=1309" rel="noopener noreferrer" target="_blank">one</a>.<br />
First, we have to generate the private key for the server. I&#8217;ll put it under <strong>/etc/certs</strong> directory.Do this by typing:</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /etc/certs
cd /etc/certs
openssl genrsa -out test2.empire.local.key 2048
</pre>
<p>Then we&#8217;ll generate a request file that the Enterprise CA will have to sign. </p>
<pre class="brush: bash; title: ; notranslate">
openssl req -new -key test2.empire.local.key -out test2.empire.local.csr
</pre>
<p>You&#8217;ll be prompted to fill out the blanks, similarly with what we did with the IIS server.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-82.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-82.png" alt="" width="554" height="194" class="aligncenter size-full wp-image-7924" /></a><br />
Remember, common name is the name of your server URL.<br />
Once you execute these two commands, you&#8217;ll have two files under /etc/certs. The private key and the the certificate signing request (.csr extension means that).<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-83.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-83.png" alt="" width="475" height="75" class="aligncenter size-full wp-image-7925" /></a><br />
The<strong> Enterprise CA</strong> will have to sign the request file and issue a certificate.<br />
Issuing this certificate is a little bit different. Go to the <strong>Enterprise CA</strong> and using a browser go to http://localhost/certsrv.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-84.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-84.png" alt="" width="786" height="455" class="aligncenter size-full wp-image-7926" /></a><br />
Click on <strong>Request a certificate</strong>. Then click on <strong>advanced certificate request</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-85.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-85.png" alt="" width="773" height="242" class="aligncenter size-full wp-image-7927" /></a><br />
Click on the second line,<strong> Submit a certificate&#8230;</strong><br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-86.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-86.png" alt="" width="757" height="322" class="aligncenter size-full wp-image-7928" /></a><br />
On the Linux/BSD server, open up the csr file under <strong>/etc/certs</strong> with your favorite editor (vi, nano, vim). It&#8217;s just a text file.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-87.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-87.png" alt="" width="500" height="312" class="aligncenter size-full wp-image-7929" /></a><br />
Select the text, copy it to the clipboard and paste it under <strong>Saved Request</strong> field.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-88.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-88.png" alt="" width="877" height="703" class="aligncenter size-full wp-image-7930" /></a><br />
For the <strong>Certificate Template</strong>, choose the <strong>Subordinate Certification Authority</strong> and click <strong>Submit</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-89.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-89.png" alt="" width="541" height="297" class="aligncenter size-full wp-image-7931" /></a><br />
Select <strong>Base 64 encoded</strong> and then you can download the certificate or the certificate chain by clicking the link. In my case, I&#8217;ll download the certificate only.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-90.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-90.png" alt="" width="675" height="300" class="aligncenter size-full wp-image-7932" /></a><br />
Save the file somewhere on the desktop (delete after use), edit it with notepad, select all and copy. This is how it looks like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-91.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-91.png" alt="" width="601" height="629" class="aligncenter size-full wp-image-7933" /></a><br />
Go back to your Linux/BSD server and edit a new file under <strong>/etc/certs</strong>. I&#8217;ll name my file test2.empire.local.crt, so I know that this is a server certificate. Paste the text from notepad and save it. Edit the httpd.conf or httpd-vhosts.conf or whatever file you have for your web server and create an entry for your web site. In my case it looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;VirtualHost *:443&gt;
    SSLEngine on
    SSLCertificateFile /etc/certs/test2.empire.local.crt
    SSLCertificateKeyFile /etc/certs/test2.empire.local.key
    ServerAdmin darth.vader@empire.local
    DocumentRoot /var/www/test2.empire.local
    ServerName test2.empire.local
    ErrorLog logs/test2.empire.local-error_log
    CustomLog logs/test2.empire.local-access_log common
&lt;/VirtualHost&gt;
</pre>
<p>Go to the root of your web site, in my case it&#8217;s <strong>/var/www/test2.empire.local</strong> and create an <strong>index.html</strong> (not .htm) file with something in it.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-92.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-92.png" alt="" width="409" height="93" class="aligncenter size-full wp-image-7934" /></a><br />
Finally, go to https://test2.empire.local and you should see the site.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/12/P094-93.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/12/P094-93.png" alt="" width="586" height="153" class="aligncenter size-full wp-image-7935" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2017/12/117-windows-enterprise-pki-windows-2016/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell, shell: Remove comments from source (Windows/Linux/BSD)</title>
		<link>https://blog.andreev.it/2016/12/103-norem-utility-remove-comments-source/</link>
					<comments>https://blog.andreev.it/2016/12/103-norem-utility-remove-comments-source/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 14 Dec 2016 15:53:14 +0000</pubDate>
				<category><![CDATA[AIX]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[OpenBSD]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Unix shell]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[remove comments]]></category>
		<category><![CDATA[sh]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=2990</guid>

					<description><![CDATA[norem for Linux/*BSD A small utility written in Bourne shell (compatible with both sh&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><h1>norem for Linux/*BSD</h1>
<p>A small utility written in Bourne shell (compatible with both <strong>sh </strong>and <strong>bash</strong>, which means works without changes on all *BSD/Linux) that strips comments from a source file. E.g. I am too lazy to scroll through <strong>/etc/ssh/sshd_config</strong> file to look for  any valid directives.<br />
Here is <strong>/etc/ssh/sshd_config</strong> on FreeBSD.</p>
<pre class="brush: plain; collapse: true; light: false; title: ; toolbar: true; notranslate">
#       $OpenBSD: sshd_config,v 1.98 2016/02/17 05:29:04 djm Exp $
#       $FreeBSD: releng/10.3/crypto/openssh/sshd_config 296853 2016-03-14 13:05:13Z des $

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

# Note that some of FreeBSD's defaults differ from OpenBSD's, and
# FreeBSD has a few additional options.

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

# The default requires explicit activation of protocol 1
#Protocol 2

# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024

# Ciphers and keying
#RekeyLimit default none

# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#RSAAuthentication yes
#PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# Change to yes to enable built-in password authentication.
#PasswordAuthentication no
#PermitEmptyPasswords no

# Change to no to disable PAM authentication
#ChallengeResponseAuthentication yes

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

# Set this to 'no' to disable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of &quot;PermitRootLogin without-password&quot;.
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#UsePrivilegeSeparation sandbox
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum FreeBSD-20160310

# no default banner path
#Banner none

# override default of no subsystems
Subsystem       sftp    /usr/libexec/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server
</pre>
<p>With this utility, I can just do:</p>
<pre class="brush: bash; title: ; notranslate">
norem -f /etc/ssh/sshd_config
</pre>
<p>&#8230; and voila&#8230;You have the meat without the bones.</p>
<pre class="brush: plain; title: ; notranslate">
Subsystem       sftp    /usr/libexec/sftp-server
</pre>
<p>Almost all *nix utilities have &#8220;#&#8221; as a comment, but some languages such as Java and C++ use &#8220;//&#8221; for comments. In this case, we have to run:</p>
<pre class="brush: bash; title: ; notranslate">
norem -f file -c &quot;/&quot;
</pre>
<p>The utility is not smart enough for multi-line comments such as &#8220;/*&#8230;*/&#8221;<br />
Here is the source:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh

usage()
{
    echo &quot;usage: norem &#x5B;-f file ] | &#x5B;-c char] | &#x5B;-e]] | &#x5B;-h]]&quot;
    echo &quot;Prints a file skipping the lines that start with -c&quot;
    echo &quot;By default empty lines are not printed, use -e yes to include them&quot;
    echo &quot;Kliment Andreev - 2016&quot;
}

if &#x5B; &quot;$#&quot; == &quot;0&quot; ]; then
        usage
        exit 1
fi

while &#x5B; $# -gt 0 ]; do
        key=&quot;$1&quot;

        case $key in
                -f|--file)
                        FILENAME=&quot;$2&quot;
                    shift
                        ;;
        -c|--char)
                        CHARACTER=&quot;$2&quot;
                        shift
                ;;
                -e|--empty)
                EMPTY=&quot;$2&quot;
                shift
                ;;
        *)
                usage
                        exit
                ;;
        esac
        shift
done

if &#x5B; -z &quot;${CHARACTER}&quot; ]; then
        CHARACTER=&quot;#&quot;
fi

if &#x5B; -z &quot;${EMPTY}&quot; ]; then
        cat ${FILENAME} | sed &quot;/^\\${CHARACTER}/d&quot; | awk /./
else
        cat ${FILENAME} |sed &quot;/^\\${CHARACTER}/d&quot;
fi
</pre>
<h1>norem for PowerShell</h1>
<p>The same utility for PowerShell. The input parameters are the same.</p>
<pre class="brush: powershell; title: ; notranslate">
Param(
	&#x5B;string]$fileName,
	&#x5B;string]$char=&quot;#&quot;,
	&#x5B;string]$empty
)

function usage {
    Write-Host &quot;usage: norem &#x5B;-f file ] | &#x5B;-c char] | &#x5B;-e]]&quot;
    Write-Host &quot;Prints a file skipping the lines that start with -c&quot;
    Write-Host &quot;By default empty lines are not printed, use -e yes to include them&quot;
    Write-Host &quot;Kliment Andreev - 2016&quot;
}

if ($psboundparameters.Count -eq 0) {
    usage
    exit
}

if ($empty.ToUpper().Contains(&quot;Y&quot;)) {
    Get-Content $fileName | Where { $_ -notmatch &quot;^&quot; + $char }
}
else {
    Get-Content $fileName | Where { $_ -notmatch &quot;^&quot; + $char } | Where {$_.trim() -ne &quot;&quot;}
}
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2016/12/103-norem-utility-remove-comments-source/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Windows: Terminal License Server or Remote Desktop Services Server on Windows 2012R2 server</title>
		<link>https://blog.andreev.it/2016/07/91-windows-2012r2-terminal-license-server-or-remote-desktop-services-server/</link>
					<comments>https://blog.andreev.it/2016/07/91-windows-2012r2-terminal-license-server-or-remote-desktop-services-server/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 06 Jul 2016 15:29:20 +0000</pubDate>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[Remote Desktop Services]]></category>
		<category><![CDATA[Terminal Server]]></category>
		<category><![CDATA[WIndows 2012R2]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=2593</guid>

					<description><![CDATA[Here is a quick way to install Terminal server on 2012R2 and specify your&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Here is a quick way to install Terminal server on 2012R2 and specify your license server. Actually, it&#8217;s called Remote Desktop services server and Remote Desktop services license server. </p>
<p>Click on <strong>Add Roles and Features Wizard</strong>. Specify <strong>Remote Desktop Services</strong> installation.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-01.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-01.jpg" alt="" width="779" height="554" class="aligncenter size-full wp-image-7510" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-01.jpg 779w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-01-300x213.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-01-768x546.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-01-585x416.jpg 585w" sizes="(max-width: 779px) 100vw, 779px" /></a><br />
Select <strong>Quick Start</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-02.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-02.jpg" alt="" width="782" height="553" class="aligncenter size-full wp-image-7511" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-02.jpg 782w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-02-300x212.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-02-768x543.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-02-585x414.jpg 585w" sizes="(max-width: 782px) 100vw, 782px" /></a><br />
Select <strong>Session-based desktop deployment</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-03.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-03.jpg" alt="" width="791" height="552" class="aligncenter size-full wp-image-7512" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-03.jpg 791w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-03-300x209.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-03-768x536.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-03-585x408.jpg 585w" sizes="(max-width: 791px) 100vw, 791px" /></a><br />
Make sure it&#8217;s the right server and click <strong>Next</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-04.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-04.jpg" alt="" width="805" height="556" class="aligncenter size-full wp-image-7513" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-04.jpg 805w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-04-300x207.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-04-768x530.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-04-585x404.jpg 585w" sizes="(max-width: 805px) 100vw, 805px" /></a><br />
Click on <strong>Restart the destination server automatically if required</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-05.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-05.jpg" alt="" width="789" height="547" class="aligncenter size-full wp-image-7514" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-05.jpg 789w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-05-300x208.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-05-768x532.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-05-585x406.jpg 585w" sizes="(max-width: 789px) 100vw, 789px" /></a><br />
Wait for the process to complete.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-06.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-06.jpg" alt="" width="871" height="730" class="aligncenter size-full wp-image-7515" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-06.jpg 871w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-06-300x251.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-06-768x644.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-06-585x490.jpg 585w" sizes="(max-width: 871px) 100vw, 871px" /></a><br />
Once completed, click on <strong>RD Licensing</strong> and then from the <strong>Tasks </strong>drop down, click on <strong>Edit Deployment Properties</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-07-1.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-07-1.jpg" alt="" width="771" height="588" class="aligncenter size-full wp-image-7518" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-07-1.jpg 771w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-07-1-300x229.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-07-1-768x586.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-07-1-585x446.jpg 585w" sizes="(max-width: 771px) 100vw, 771px" /></a><br />
Choose the licensing mode, type the license server name, click <strong>Add </strong>and OK.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2016/07/P070-08-1.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/07/P070-08-1.jpg" alt="" width="753" height="590" class="aligncenter size-full wp-image-7519" srcset="https://blog.andreev.it/wp-content/uploads/2016/07/P070-08-1.jpg 753w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-08-1-300x235.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/07/P070-08-1-585x458.jpg 585w" sizes="(max-width: 753px) 100vw, 753px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2016/07/91-windows-2012r2-terminal-license-server-or-remote-desktop-services-server/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell: CommVault report from vCenter</title>
		<link>https://blog.andreev.it/2016/06/90-windowspowershell-commvault-report-in-vcenter/</link>
					<comments>https://blog.andreev.it/2016/06/90-windowspowershell-commvault-report-in-vcenter/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Thu, 30 Jun 2016 15:34:58 +0000</pubDate>
				<category><![CDATA[ESX/ESXi]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[CommVault]]></category>
		<category><![CDATA[vCenter]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=2603</guid>

					<description><![CDATA[Recently, we moved to CommVault for backing up VMs. We use a CommVault solution&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Recently, we moved to CommVault for backing up VMs. We use a CommVault solution that interacts with NetApp for taking snaps. Once the backup runs, it time-stamps the VM with the last backup taken. If you don&#8217;t need an e-mail in HTML format with the report, remove the lines from 103 to 113. Finally, remove the comment line # from line 57 if you want the report on the screen.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2016/06/P069-01.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/06/P069-01.jpg" alt="" width="360" height="170" class="aligncenter size-full wp-image-7488" srcset="https://blog.andreev.it/wp-content/uploads/2016/06/P069-01.jpg 360w, https://blog.andreev.it/wp-content/uploads/2016/06/P069-01-300x142.jpg 300w" sizes="(max-width: 360px) 100vw, 360px" /></a><br />
Based on this info, I made a script that loops through all clusters and VMs and dumps the report in a mail. You can remove lines 5 to 14 if you don&#8217;t want the script scheduled. </p>
<pre class="brush: powershell; title: ; notranslate">
# PowerCLI script that lists all VMs under clusters that start with USCORPROD*
# and prints the Last Backup attribute from CommVault
# If the difference between the run time of the script and the last backup is
# more than $HoursDifference, write the output with red color
Add-PSSnapin VMware.VimAutomation.Core
Add-PSSnapin VMware.VimAutomation.Vds
if(get-item HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns\VMware.VimAutomation.Core){
	. ((get-item HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns\VMware.VimAutomation.Core).GetValue(&quot;ApplicationBase&quot;)+&quot;\Scripts\Initialize-PowerCLIEnvironment.ps1&quot;)
}
else
{
	write-warning &quot;PowerCLI Path not found in registry, please set path to Initialize-PowerCLIEnvironment.ps1 manually. Is PowerCli aleady installed?&quot;
	. &quot;D:\Programs (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1&quot;
}

# Specify the vCenter server
$server = &quot;vcenter&quot;
# Specify the difference in hours to compare
$HoursDifferenceCompare = 24
# Cluster filter
$ClusterFilter = &quot;*&quot;
# Connect to vCenter
Connect-VIServer -Server $server -user domain\username -password vcpassword
# Initalize the main HTML content
$midHTML=&quot;&quot;
# Get each cluster that starts with $ClusterFilter and sort them. 
# Make sure only unique values are returned
ForEach ($Cluster in Get-Cluster $ClusterFilter | Sort -unique)
{
	# Get all the VMs per cluster
	$VMs = Get-Cluster $Cluster | Get-VM 
	# Loop each VM
	ForEach ($VM in $VMs)
	{
		# Get the last backup attribute
		$LastBackup = Get-VM $VM | Get-Annotation -CustomAttribute &quot;Last Backup&quot;
		# Parse the output, trinm the string
		$LastBackupTimeStamp = $LastBackup -replace &quot;Last Backup:&quot;
		# Get the date/time when the script started
		$StartDate=(Get-Date)
		# The end date is the Last Backup time for the VM
		# If the VM was never backed up, assume 01/01/70
		if ($LastBackupTimeStamp -eq '') {
			$EndDate = &#x5B;datetime]'January 1, 1970'
			$LastBackupTimeStamp = &quot;NEVER&quot;}
		else {
			$EndDate = &#x5B;datetime]$LastBackupTimeStamp 
			}
		# Calculate the difference
		$TimeSpan = New-TimeSpan -Start $StartDate -End $EndDate
		# It's a negative value, so get the absolute
		$DaysDifference = &#x5B;math]::abs($TimeSpan.Days)
		$HoursDifference = &#x5B;math]::abs($TimeSpan.Hours) + ($DaysDifference * 24)
		# Print the output
		if ($HoursDifference -gt $HoursDifferenceCompare) {
			# Remove for debugging if needed
			#Write-Host $Cluster &quot; &quot; $VM &quot; &quot; $LastBackupTimeStamp
			# Build the HTML
			$midHTML = $midHTML + '&lt;font color=&quot;red&quot;&gt;'
			$midHTML = $midHTML + &quot;&lt;p&gt;&quot; + $Cluster + &quot; &quot; + $VM.Name.PadRight(30,&quot;-&quot;) + &quot; &quot; + $LastBackupTimeStamp + &quot;&lt;/p&gt;&quot;
			$midHTML = $midHTML + &quot;&lt;/font&gt;&quot;
		} else {
			$midHTML = $midHTML + &quot;&lt;p&gt;&quot; + $Cluster + &quot; &quot; + $VM.Name.PadRight(30,&quot;-&quot;) + &quot; &quot; + $LastBackupTimeStamp + &quot;&lt;/p&gt;&quot;
		}
	}	
}

# Top HTML header
$topHTML = @&quot;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
&lt;font face=&quot;Courier New, Courier, monospace&quot;&gt;
&lt;style&gt;
p
{
  margin:0;
  padding:0;
  font-size:12px;
    line-height:12px;
}
div
{
  margin:0;
  padding:0;
}
&lt;/style&gt;
&lt;div&gt;
&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;CLUSTER NAME&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;SERVER NAME&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;DATE OF LAST BACKUP&lt;/p&gt;
&lt;p&gt;-----------------------------------------------------------------------&lt;/p&gt;
&quot;@

# Bottom HTML footer
$bottomHTML = @&quot;
&lt;p&gt;-----------------------------------------------------------------------&lt;/p&gt;
&lt;p&gt;Script by K.Andreev - 20160630&lt;/p&gt;
&lt;/div&gt;
&lt;/font&gt;
&lt;/body&gt;
&lt;/html&gt;
&quot;@

# e-mail setup
$EmailFrom =&quot;sender@domain.com&quot;
$EmailTo =&quot;receiver@domain.com&quot;
$msg = New-Object System.Net.Mail.MailMessage ($EmailFrom,$EmailTo)
$msg.subject = &quot;CommVault Report &quot; + $StartDate
$msg.IsBodyHtml = $true;
$msg.Body =$topHTML + $midHTML + $bottomHTML
$smtpClient = New-Object System.Net.Mail.SmtpClient
$smtpClient.Host = &quot;smtp.server.com&quot;
$smtpClient.EnableSsl = $false
$smtpClient.Send($msg)

# Disconnect from vCenter
Disconnect-VIServer -Server $Server -Confirm:$false
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2016/06/90-windowspowershell-commvault-report-in-vcenter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
