<?xml version="1.0" encoding="utf-8"?><!-- generator="b2evolution/7.2.5-stable" -->
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>George's Weblog</title>
		<link>https://george.bike/</link>
		<atom:link rel="self" type="application/rss+xml" href="https://george.bike/?tempskin=_rss2" />
		<description></description>
		<language>en-US</language>
		<docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<admin:generatorAgent rdf:resource="http://b2evolution.net/?v=7.2.5-stable"/>
		<ttl>60</ttl>
				<item>
			<title>Use Netbox as backend for Oxidized</title>
			<link>https://george.bike/?p=93&amp;more=1</link>
			<pubDate>Mon, 24 Jun 2024 13:27:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Networking</category>			<guid isPermaLink="false">93@https://george.bike/</guid>
						<description>&lt;p&gt;I had been keeping the databases separate for netbox and oxidized so thought I would integrate the two. The information on how to do it was a bit scattered so I&#039;m documenting it here.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;First of all, netbox has the interfaces we need to interface oxidized directly without the need of any external scripts. There are three parts that need to be built:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;1. Come up with a query that can be used against the netbox api that will yield the hosts you want to monitor in oxidized. My use case has stacked switches and the netbox REST view for virtual chassis doesn&#039;t have a hostname. So instead I decided to do it in a more atomic way by using a custom field on the device. That gives me a simple way to turn oxidized configuration management on and off for any device. For a switch stack I simply turn it on for the master switch element.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-20-09.png?mtime=1719231673&quot; rel=&quot;lightbox[p93]&quot; id=&quot;link_139&quot;&gt;&lt;img alt=&quot;Use Netbox as backend for Oxidized&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-20-09.png/fit-320x320.png?mtime=1719231673&quot; width=&quot;400&quot; height=&quot;204&quot; class=&quot;evo_thumbnail evo_thumbnail__left loadimg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;I also added a custom field for the &lt;a href=&quot;http://www.tellmewhatis.com/dns-domain-name-system&quot;&gt;DNS&lt;/a&gt; name. You may be able to use your device name instead depending on your setup.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-27-14.png?mtime=1719232073&quot; rel=&quot;lightbox[p93]&quot; id=&quot;link_140&quot;&gt;&lt;img alt=&quot;Use Netbox as backend for Oxidized&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-27-14.png/fit-320x320.png?mtime=1719232073&quot; width=&quot;400&quot; height=&quot;202&quot; class=&quot;evo_thumbnail evo_thumbnail__left loadimg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;2. The second part of the config is in oxidized. Fortunately oxidized has an http interface that can read the netbox data directly.&lt;/p&gt;
&lt;p&gt;You&#039;ll need to generate an api token in netbox first. So navigate to Admin, API Tokens, click Add and create an appropriate key. You may want to create a user that just has read-only permissions to the device data for security.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-52-35.png?mtime=1719235163&quot; rel=&quot;lightbox[p93]&quot; id=&quot;link_145&quot;&gt;&lt;img alt=&quot;Use Netbox as backend for Oxidized&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-52-35.png/fit-320x320.png?mtime=1719235163&quot; width=&quot;400&quot; height=&quot;283&quot; class=&quot;evo_thumbnail evo_thumbnail__left loadimg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Next we must configure oxidized for an http source. Here is the relevant portion of the oxidized config file:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-30-05.png?mtime=1719232340&quot; rel=&quot;lightbox[p93]&quot; id=&quot;link_141&quot;&gt;&lt;img alt=&quot;Use Netbox as backend for Oxidized&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-30-05.png/fit-320x320.png?mtime=1719232340&quot; width=&quot;400&quot; height=&quot;114&quot; class=&quot;evo_thumbnail evo_thumbnail__left loadimg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Important to note is that when calling the netbox REST api you embed cf_oxidized_enrolled as a filter and also test to make sure the device is active. The last URL parameter is needed if you have more than 50 devices because the netbox api will only return up to 50 results by default.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The part below the map: specifies which fields oxidized &quot;maps&quot; to its own fields. Here I use my custom field for both the name and ip address. I use the platform name as the model; that&#039;s a standard field in netbox. If you think you want to map different fields, remember that you can view the api data formats pretty easily by visiting &lt;a href=&quot;https://your.netbox.url/api&quot; class=&quot;linebreak&quot;&gt;https://your.netbox.url/api&lt;/a&gt; and then drill down to the dcim/devices section and look at the output. You can also test your filter that way. NOTE: the field you use for model must match a defined model in oxidized.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;3. The final step is to create a trigger that will make oxidized refresh its device database when a device is added, removed or modified. We do that in netbox. Create a webhook (Operations, Webhooks, Add) and fill in the fields. The URL field will be your oxidized URL with /reload appended.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-56-37.png?mtime=1719234001&quot; rel=&quot;lightbox[p93]&quot; id=&quot;link_143&quot;&gt;&lt;img alt=&quot;Use Netbox as backend for Oxidized&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-56-37.png/fit-320x320.png?mtime=1719234001&quot; width=&quot;153&quot; height=&quot;300&quot; class=&quot;evo_thumbnail evo_thumbnail__left loadimg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;To make sure we only trigger an oxidized config reload when we&#039;re modifying a relevant object, we can set an event rule (Operations, Event Rules, Add):&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_09-02-34.png?mtime=1719234191&quot; rel=&quot;lightbox[p93]&quot; id=&quot;link_144&quot;&gt;&lt;img alt=&quot;Use Netbox as backend for Oxidized&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_09-02-34.png/fit-320x320.png?mtime=1719234191&quot; width=&quot;109&quot; height=&quot;300&quot; class=&quot;evo_thumbnail evo_thumbnail__left loadimg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Test everything and make sure you can add/delete a device and trigger a reload.&lt;/p&gt;
&lt;p&gt;That&#039;s it!&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=93&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>I had been keeping the databases separate for netbox and oxidized so thought I would integrate the two. The information on how to do it was a bit scattered so I'm documenting it here.</p>
<p> </p>
<p>First of all, netbox has the interfaces we need to interface oxidized directly without the need of any external scripts. There are three parts that need to be built:</p>
<p> </p>
<p>1. Come up with a query that can be used against the netbox api that will yield the hosts you want to monitor in oxidized. My use case has stacked switches and the netbox REST view for virtual chassis doesn't have a hostname. So instead I decided to do it in a more atomic way by using a custom field on the device. That gives me a simple way to turn oxidized configuration management on and off for any device. For a switch stack I simply turn it on for the master switch element.</p>
<p> </p>
<p><a href="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-20-09.png?mtime=1719231673" rel="lightbox[p93]" id="link_139"><img alt="Use Netbox as backend for Oxidized" src="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-20-09.png/fit-320x320.png?mtime=1719231673" width="400" height="204" class="evo_thumbnail evo_thumbnail__left loadimg" /></a></p>
<p> </p>
<p>I also added a custom field for the <a href="http://www.tellmewhatis.com/dns-domain-name-system">DNS</a> name. You may be able to use your device name instead depending on your setup.</p>
<p> </p>
<p><a href="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-27-14.png?mtime=1719232073" rel="lightbox[p93]" id="link_140"><img alt="Use Netbox as backend for Oxidized" src="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-27-14.png/fit-320x320.png?mtime=1719232073" width="400" height="202" class="evo_thumbnail evo_thumbnail__left loadimg" /></a></p>
<p> </p>
<p>2. The second part of the config is in oxidized. Fortunately oxidized has an http interface that can read the netbox data directly.</p>
<p>You'll need to generate an api token in netbox first. So navigate to Admin, API Tokens, click Add and create an appropriate key. You may want to create a user that just has read-only permissions to the device data for security.</p>
<p> </p>
<p><a href="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-52-35.png?mtime=1719235163" rel="lightbox[p93]" id="link_145"><img alt="Use Netbox as backend for Oxidized" src="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-52-35.png/fit-320x320.png?mtime=1719235163" width="400" height="283" class="evo_thumbnail evo_thumbnail__left loadimg" /></a></p>
<p> </p>
<p>Next we must configure oxidized for an http source. Here is the relevant portion of the oxidized config file:</p>
<p> </p>
<p><a href="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-30-05.png?mtime=1719232340" rel="lightbox[p93]" id="link_141"><img alt="Use Netbox as backend for Oxidized" src="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-30-05.png/fit-320x320.png?mtime=1719232340" width="400" height="114" class="evo_thumbnail evo_thumbnail__left loadimg" /></a></p>
<p> </p>
<p>Important to note is that when calling the netbox REST api you embed cf_oxidized_enrolled as a filter and also test to make sure the device is active. The last URL parameter is needed if you have more than 50 devices because the netbox api will only return up to 50 results by default.</p>
<p> </p>
<p>The part below the map: specifies which fields oxidized "maps" to its own fields. Here I use my custom field for both the name and ip address. I use the platform name as the model; that's a standard field in netbox. If you think you want to map different fields, remember that you can view the api data formats pretty easily by visiting <a href="https://your.netbox.url/api" class="linebreak">https://your.netbox.url/api</a> and then drill down to the dcim/devices section and look at the output. You can also test your filter that way. NOTE: the field you use for model must match a defined model in oxidized.</p>
<p> </p>
<p>3. The final step is to create a trigger that will make oxidized refresh its device database when a device is added, removed or modified. We do that in netbox. Create a webhook (Operations, Webhooks, Add) and fill in the fields. The URL field will be your oxidized URL with /reload appended.</p>
<p> </p>
<p><a href="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_08-56-37.png?mtime=1719234001" rel="lightbox[p93]" id="link_143"><img alt="Use Netbox as backend for Oxidized" src="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_08-56-37.png/fit-320x320.png?mtime=1719234001" width="153" height="300" class="evo_thumbnail evo_thumbnail__left loadimg" /></a></p>
<p> </p>
<p>To make sure we only trigger an oxidized config reload when we're modifying a relevant object, we can set an event rule (Operations, Event Rules, Add):</p>
<p> </p>
<p><a href="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/2024-06-24_09-02-34.png?mtime=1719234191" rel="lightbox[p93]" id="link_144"><img alt="Use Netbox as backend for Oxidized" src="https://george.bike/media/blogs/george/quick-uploads/use-netbox-as-backend-for/.evocache/2024-06-24_09-02-34.png/fit-320x320.png?mtime=1719234191" width="109" height="300" class="evo_thumbnail evo_thumbnail__left loadimg" /></a></p>
<p> </p>
<p>Test everything and make sure you can add/delete a device and trigger a reload.</p>
<p>That's it!</p><div class="item_footer"><p><small><a href="https://george.bike/?p=93&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=93&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=93</wfw:commentRss>
		</item>
				<item>
			<title>Integrating Ansible with Hashicorp Vault</title>
			<link>https://george.bike/?p=92&amp;more=1</link>
			<pubDate>Thu, 15 Dec 2022 00:29:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Mac</category>
<category domain="alt">Linux</category>			<guid isPermaLink="false">92@https://george.bike/</guid>
						<description>&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;There are several moving parts of this configuration. We’re using a simple example here; your implementation may have different requirements.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;First, vault should be installed and working in a production configuration. For these examples we have the root token in our possession. You may not need this for your deployment if you have the correct permissions already assigned to your local account.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;To use these examples you will need hvac python library and community.hashi_vault collection installed. Install hvac library with ‘pip install hvac’. Install the community package with ‘ansible-galaxy collection install community.hashi_vault’.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;You can use Hashicorp Vault to store all the sensitive variables you use with ansible. However, you still need to have a credential to authenticate ansible against vault. We will explore using a token or alternatively a username/password against an LDAP (Active Directory) backend for authentication.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;When using vault from the command line you can use a token from an environment variable, or you can specify your username and you will need to type your password. Generally, you will only use this to write variables for ansible to read. You can also likely do it through the vault GUI if you have set that up.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;When running ansible plays, the token or username and password can be set as environment variables manually or from your .profile or .bashrc if you wish. Obviously, it’s more secure to set them manually for your session and not store them on the server.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Let’s go through storing some key value pairs and setting up a policy to access them. We’ll then show how to retrieve them and use them in an ansible playbook.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Let’s put our server address and root token into the environment.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;strong&gt;$ export VAULT_ADDR=&quot;https://vault.example.com:8200&quot;&lt;br /&gt;&lt;/strong&gt;&lt;/code&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ export VAULT_TOKEN=&quot;hvs.hrlxewcxyxyxyxyxyxy&quot;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now we’ll create a token that is valid for a year and can be refreshed every 30 days. We will set the default max lease time for tokens.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault write sys/auth/token/tune max_lease_ttl=8760h&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;code&gt;&lt;strong&gt;Success! Data written to: sys/auth/token/tune&lt;/strong&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;background-color: #999999; font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: arial, helvetica, sans-serif; background-color: #ffffff;&quot;&gt;Let’s create a path for some vmware credentials, we’ll use the key-value storage version 2:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault secrets enable -path=apps kv-v2&lt;br /&gt;Success! Enabled the kv-v2 secrets engine at: apps/&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now we’ll put our vcenter username and password in there.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;strong&gt;$ vault kv put apps/vmware vcenter_username=&quot;administrator@vsphere.local&quot;&lt;/strong&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/code&gt;&lt;strong&gt;&lt;code&gt;$ vault kv patch apps/vmware vcenter_password=&quot;SomeVerySecretPassword&quot;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Check to make sure you can read them okay.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault kv get apps/vmware&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;strong&gt;== Secret Path ==&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;apps/data/vmware&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;======= Metadata =======&lt;/strong&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;Key                Value&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;---                -----&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;created_time       2022-12-13T22:16:24.625488264Z&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;custom_metadata    &lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;deletion_time      n/a&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;destroyed          false&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;version            3&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;========== Data ==========&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;Key                 Value&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;---                 -----&lt;br /&gt;&lt;/strong&gt;&lt;strong style=&quot;color: #24292e;&quot;&gt;vcenter_password    SomeVerySecretPassword&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;vcenter_username    vadministrator@vsphere.local&lt;/strong&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;If you only want one value, use the -field parameter to get it:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault kv get -field vcenter_username apps/vmware&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;administrator@vsphere.local&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;background-color: #99ccff; font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now that we have a few values stored we need to create a policy to allow access to them. Make up a policy file called app-policy.hcl that looks like this:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;strong&gt;path &quot;apps/*&quot;&lt;/strong&gt; &lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;strong&gt;&lt;code&gt;&lt;code&gt;  {&lt;/code&gt;capabilities = [&quot;read&quot;]&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;}&lt;/code&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Create a new policy and pull in the file:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault policy write app-reader app-policy.hcl&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;Success! Uploaded policy: app-reader&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Make a token an associate it to the policy:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault token create -display-name app-reader -explicit-max-ttl 8760h -policy app-reader -ttl 720h -renewable&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;Key                  Value&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;---                  -----&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;token                hvs.CAESIFLCj9VhI2IHzKeTNtMOJGPVxyxyxyxy&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;token_accessor       RJb1xyxyxyxy&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;token_duration       720h&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;token_renewable      true&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;token_policies       [&quot;app-reader&quot; &quot;default&quot;]&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;identity_policies    []&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;policies             [&quot;app-reader&quot; &quot;default&quot;]&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;You can confirm the ability to read the secrets:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;code&gt;$ vault token capabilities hvs.CAESIFLCj9VhI2IHzKeTNtMOJGPVxyxyxyxy&lt;/code&gt;&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;strong&gt;&lt;code&gt;read&lt;/code&gt;&lt;/strong&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now that secrets are stored, we can read them with a playbook. In this example we will be accessing a VMware vCenter server. The non-sensitive variables are in a file called vars.yml that looks like this:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;---&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_hostname: &quot;vcenter.example.com&quot;&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;strong style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;code&gt;vcenter_datacenter: &quot;EXAMPLE&quot;&lt;br /&gt;&lt;/code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_cluster: &quot;Cluster1&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_datastore: &quot;SAN&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_validate_certs: false&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_destination_folder: &quot;EXAMPLE&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_content_library: &quot;example&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vm_template: &quot;linux-ubuntu-20.04lts-v22.11&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vm_state: &quot;poweroff&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;ansible_hashi_vault_url: &#039;https://vault.example.com:8200&#039;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;ansible_hashi_vault_auth_method: token&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Notice the last two variables defined. They are used by the hashi_vault module.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;The last thing to do before running a playbook is to store our token into the expected environment variable like this:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ export ANSIBLE_HASHI_VAULT_TOKEN=hvs.CAESIFLCj9Vxyxyxyxyxy&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;We can put together a playbook that uses the credentials from vault. Here is one that powers up some VMs from our inventory:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;---&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;- name: start inactive vms&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  hosts: localhost&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  become: false&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  gather_facts: false&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  collections:&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;    - community.vmware&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  pre_tasks:&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;    - include_vars: vars.yml&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  tasks:&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;    - name: get vcenter credentials from hashicorp vault&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;      set_fact:&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        vcenter_username: &quot;{{ lookup(&#039;hashi_vault&#039;, &#039;secret=apps/data/vmware:vcenter_username&#039;) }}&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        vcenter_password: &quot;{{ lookup(&#039;hashi_vault&#039;, &#039;secret=apps/data/vmware:vcenter_password&#039;) }}&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;    - name: power on&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;      vmware_guest_powerstate:&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        hostname: &quot;{{ vcenter_hostname }}&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        username: &quot;{{ vcenter_username }}&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        password: &quot;{{ vcenter_password }}&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        name: &quot;{{ item }}&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        validate_certs: &quot;{{ vcenter_validate_certs }}&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;        state: powered-on&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;      loop: &quot;{{ lookup(&#039;inventory_hostnames&#039;, &#039;inactive:&amp;amp;ubuntu22&#039;, wantlist=True) }}&quot;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;As an alternative, a username and password can be used for authentication. In this scenario we will use LDAP (Active Directory) to authenticate the user.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;We use our root credential on vault to enable the ldap authentication mechanism on vault:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ export VAULT_TOKEN=hvs.hrlxewxyxyxyxy&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault auth enable ldap&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now let’s configure the ldap to talk to our domain controller. We’ve already built a user called ‘vault’ in active directory so we can bind with that user here. We’re not using any certificates for simplicity, it would be a better idea to use ldaps in production.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault write auth/ldap/config \&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  url=&quot;ldap://dc01.ad.example.com&quot; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  userattr=&quot;sAMAccountName&quot; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  userdn=&quot;cn=Users,dc=ad,dc=example,dc=com&quot; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  groupdn=&quot;cn=Users,dc=ad,dc=example,dc=com&quot; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  groupfilter=&quot;(&amp;amp;(objectClass=group)(member={{.UserDN}}))&quot; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  groupattr=&quot;memberOf&quot; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  binddn=&quot;cn=vault,cn=users,dc=ad,dc=example,dc=com&quot; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  bindpass=&#039;FNjRdTTzxyxyxy&#039; \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  starttls=false \&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;  userfilter=&quot;({{.UserAttr}}={{.Username}})&quot;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now that we can authenticate to vault via ldap, we can use ldap groups to set user policy. Let’s reuse the policy we built previously and bind it to the vaultusers group:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault write auth/ldap/groups/vaultusers policies=app-reader&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Let’s log in and test our access from the CLI. We’ll make sure we have our server location set in the environment first:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ export VAULT_ADDR=https://vault.example.com:8200/&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now we log in with username/password:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault login -method=ldap username=ansible&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;Password (will be hidden):&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;Success! You are now authenticated. The token information displayed below&lt;br /&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;is already stored in the token helper. You do NOT need to run &quot;vault login&quot;&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;again. Future Vault requests will automatically use this token. &lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;Key                    Value&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;---                    -----&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;token                  hvs.CAESICz0NC0UNUTW1nyxyxyxyxy&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;token_accessor         jXIisU1vaHRGRkxyxyxyxy&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;token_duration         768h&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;token_renewable        true&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;token_policies         [&quot;app-reader&quot; &quot;default&quot;]&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;identity_policies      []&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;policies               [&quot;app-reader&quot; &quot;default&quot;]&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;token_meta_username    ansible&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Since ‘ansible’ is a member of the ‘vaultusers’ security group in AD, you can see that we have the “app-reader” policy applied (in addition to default). So let’s see if we can read our vcenter credentials:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ vault kv get apps/vmware&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;== Secret Path ==&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;apps/data/vmware&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;======= Metadata =======&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;Key                Value&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;---                -----&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;created_time       2022-12-13T22:16:24.625488264Z&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;custom_metadata    &lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;deletion_time      n/a&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;destroyed          false&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;version            3&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;========== Data ==========&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;Key                 Value&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;---                 -----&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_password    SomeVerySecretPassword&lt;/code&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;vcenter_username    administrator@vsphere.local&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Success!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;To use username and password credentials in our playbook, instead of setting a token in an environment variable we set our username and password instead:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ export ANSIBLE_HASHI_VAULT_USERNAME=&quot;ansible&quot;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;$ export ANSIBLE_HASHI_VAULT_PASSWORD=&quot;YouWontEverGuessIt&quot;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;strong&gt;&lt;code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;We also need to change the line in our vars.yml to specify ldap instead of token auth:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;strong&gt;ansible_hashi_vault_auth_method: ldap&lt;/strong&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt;&lt;span style=&quot;font-family: arial, helvetica, sans-serif;&quot;&gt;Now our playbook will run using username/password against ldap instead of requiring a token.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: 400;&quot;&gt; &lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=92&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">There are several moving parts of this configuration. We’re using a simple example here; your implementation may have different requirements.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">First, vault should be installed and working in a production configuration. For these examples we have the root token in our possession. You may not need this for your deployment if you have the correct permissions already assigned to your local account.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">To use these examples you will need hvac python library and community.hashi_vault collection installed. Install hvac library with ‘pip install hvac’. Install the community package with ‘ansible-galaxy collection install community.hashi_vault’.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">You can use Hashicorp Vault to store all the sensitive variables you use with ansible. However, you still need to have a credential to authenticate ansible against vault. We will explore using a token or alternatively a username/password against an LDAP (Active Directory) backend for authentication.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">When using vault from the command line you can use a token from an environment variable, or you can specify your username and you will need to type your password. Generally, you will only use this to write variables for ansible to read. You can also likely do it through the vault GUI if you have set that up.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">When running ansible plays, the token or username and password can be set as environment variables manually or from your .profile or .bashrc if you wish. Obviously, it’s more secure to set them manually for your session and not store them on the server.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Let’s go through storing some key value pairs and setting up a policy to access them. We’ll then show how to retrieve them and use them in an ansible playbook.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Let’s put our server address and root token into the environment.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code><strong>$ export VAULT_ADDR="https://vault.example.com:8200"<br /></strong></code></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ export VAULT_TOKEN="hvs.hrlxewcxyxyxyxyxyxy"</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span><span style="font-family: arial, helvetica, sans-serif;">Now we’ll create a token that is valid for a year and can be refreshed every 30 days. We will set the default max lease time for tokens.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault write sys/auth/token/tune max_lease_ttl=8760h<br /></code></strong><code><strong>Success! Data written to: sys/auth/token/tune</strong></code></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code></code></span></p>
<p><span style="background-color: #999999; font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="color: #000000; font-family: arial, helvetica, sans-serif; background-color: #ffffff;">Let’s create a path for some vmware credentials, we’ll use the key-value storage version 2:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault secrets enable -path=apps kv-v2<br />Success! Enabled the kv-v2 secrets engine at: apps/</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Now we’ll put our vcenter username and password in there.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code><strong>$ vault kv put apps/vmware vcenter_username="administrator@vsphere.local"</strong><strong><br /></strong></code><strong><code>$ vault kv patch apps/vmware vcenter_password="SomeVerySecretPassword"</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Check to make sure you can read them okay.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault kv get apps/vmware<br /></code></strong></span></p>
<p><code></code></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code><strong>== Secret Path ==<br /></strong><strong>apps/data/vmware<br /></strong><strong>======= Metadata =======</strong><strong><br /></strong><strong style="color: #24292e;">Key                Value<br /></strong><strong style="color: #24292e;">---                -----<br /></strong><strong style="color: #24292e;">created_time       2022-12-13T22:16:24.625488264Z<br /></strong><strong style="color: #24292e;">custom_metadata    <br /></strong><strong style="color: #24292e;">deletion_time      n/a<br /></strong><strong style="color: #24292e;">destroyed          false<br /></strong><strong style="color: #24292e;">version            3<br /></strong><strong style="color: #24292e;">========== Data ==========<br /></strong><strong style="color: #24292e;">Key                 Value<br /></strong><strong style="color: #24292e;">---                 -----<br /></strong><strong style="color: #24292e;">vcenter_password    SomeVerySecretPassword<br /></strong><strong>vcenter_username    vadministrator@vsphere.local</strong></code></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code></code></span></p>
<p><code></code></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">If you only want one value, use the -field parameter to get it:</span></p>
<p style="font-weight: 400;"> </p>
<p><code></code></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault kv get -field vcenter_username apps/vmware<br /></code></strong></span><strong style="font-family: arial, helvetica, sans-serif;"><code>administrator@vsphere.local</code></strong></p>
<p style="font-weight: 400;"><strong style="font-family: arial, helvetica, sans-serif;"><code></code></strong></p>
<p><code></code></p>
<p style="font-weight: 400;"><span style="background-color: #99ccff; font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Now that we have a few values stored we need to create a policy to allow access to them. Make up a policy file called app-policy.hcl that looks like this:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code><strong>path "apps/*"</strong> <br /></code></span><span style="font-family: arial, helvetica, sans-serif;"><code></code><strong><code><code>  {</code>capabilities = ["read"]<br /></code></strong></span><strong><span style="font-family: arial, helvetica, sans-serif;"><code>}</code></span></strong></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Create a new policy and pull in the file:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault policy write app-reader app-policy.hcl</code></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code><br /></code></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>Success! Uploaded policy: app-reader</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Make a token an associate it to the policy:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault token create -display-name app-reader -explicit-max-ttl 8760h -policy app-reader -ttl 720h -renewable</code></strong></span></p>
<p style="font-weight: 400;"> </p>
<p><code></code></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>Key                  Value<br /></code></strong></span><strong style="font-family: arial, helvetica, sans-serif;"><code>---                  -----<br /></code></strong><strong style="font-family: arial, helvetica, sans-serif;"><code>token                hvs.CAESIFLCj9VhI2IHzKeTNtMOJGPVxyxyxyxy<br /></code></strong><strong style="font-family: arial, helvetica, sans-serif;"><code>token_accessor       RJb1xyxyxyxy<br /></code></strong><strong style="font-family: arial, helvetica, sans-serif;"><code>token_duration       720h<br /></code></strong><strong style="font-family: arial, helvetica, sans-serif;"><code>token_renewable      true<br /></code></strong><strong style="font-family: arial, helvetica, sans-serif;"><code>token_policies       ["app-reader" "default"]<br /></code></strong><strong style="font-family: arial, helvetica, sans-serif;"><code>identity_policies    []<br /></code></strong><strong style="font-family: arial, helvetica, sans-serif;"><code>policies             ["app-reader" "default"]</code></strong></p>
<p style="font-weight: 400;"><strong style="font-family: arial, helvetica, sans-serif;"><code></code></strong></p>
<p><code></code></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">You can confirm the ability to read the secrets:</span></p>
<p style="font-weight: 400;"> </p>
<blockquote><p><span style="font-family: arial, helvetica, sans-serif;"><strong><code><code>$ vault token capabilities hvs.CAESIFLCj9VhI2IHzKeTNtMOJGPVxyxyxyxy</code><br /></code></strong></span><span style="font-family: arial, helvetica, sans-serif;"><code><strong><code>read</code></strong></code></span></p></blockquote>
<blockquote><p><span style="font-family: arial, helvetica, sans-serif;"><code><strong><code></code></strong></code></span></p></blockquote>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Now that secrets are stored, we can read them with a playbook. In this example we will be accessing a VMware vCenter server. The non-sensitive variables are in a file called vars.yml that looks like this:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>---</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_hostname: "vcenter.example.com"<br /></code></strong></span><strong style="font-family: arial, helvetica, sans-serif;"><code><code>vcenter_datacenter: "EXAMPLE"<br /></code></code></strong><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_cluster: "Cluster1"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_datastore: "SAN"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_validate_certs: false</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_destination_folder: "EXAMPLE"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_content_library: "example"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vm_template: "linux-ubuntu-20.04lts-v22.11"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vm_state: "poweroff"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>ansible_hashi_vault_url: 'https://vault.example.com:8200'</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>ansible_hashi_vault_auth_method: token</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Notice the last two variables defined. They are used by the hashi_vault module.</span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">The last thing to do before running a playbook is to store our token into the expected environment variable like this:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ export ANSIBLE_HASHI_VAULT_TOKEN=hvs.CAESIFLCj9Vxyxyxyxyxy</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">We can put together a playbook that uses the credentials from vault. Here is one that powers up some VMs from our inventory:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>---<br /></code></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>- name: start inactive vms</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  hosts: localhost</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  become: false</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  gather_facts: false</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  collections:</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>    - community.vmware</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  pre_tasks:</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>    - include_vars: vars.yml</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  tasks:</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>    - name: get vcenter credentials from hashicorp vault</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>      set_fact:</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        vcenter_username: "{{ lookup('hashi_vault', 'secret=apps/data/vmware:vcenter_username') }}"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        vcenter_password: "{{ lookup('hashi_vault', 'secret=apps/data/vmware:vcenter_password') }}"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>    - name: power on</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>      vmware_guest_powerstate:</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        hostname: "{{ vcenter_hostname }}"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        username: "{{ vcenter_username }}"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        password: "{{ vcenter_password }}"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        name: "{{ item }}"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        validate_certs: "{{ vcenter_validate_certs }}"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>        state: powered-on</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>      loop: "{{ lookup('inventory_hostnames', 'inactive:&amp;ubuntu22', wantlist=True) }}"</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">As an alternative, a username and password can be used for authentication. In this scenario we will use LDAP (Active Directory) to authenticate the user.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">We use our root credential on vault to enable the ldap authentication mechanism on vault:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ export VAULT_TOKEN=hvs.hrlxewxyxyxyxy</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault auth enable ldap</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Now let’s configure the ldap to talk to our domain controller. We’ve already built a user called ‘vault’ in active directory so we can bind with that user here. We’re not using any certificates for simplicity, it would be a better idea to use ldaps in production.</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault write auth/ldap/config \<br /></code></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  url="ldap://dc01.ad.example.com" \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  userattr="sAMAccountName" \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  userdn="cn=Users,dc=ad,dc=example,dc=com" \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  groupdn="cn=Users,dc=ad,dc=example,dc=com" \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  groupfilter="(&amp;(objectClass=group)(member={{.UserDN}}))" \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  groupattr="memberOf" \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  binddn="cn=vault,cn=users,dc=ad,dc=example,dc=com" \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  bindpass='FNjRdTTzxyxyxy' \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  starttls=false \</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>  userfilter="({{.UserAttr}}={{.Username}})"</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Now that we can authenticate to vault via ldap, we can use ldap groups to set user policy. Let’s reuse the policy we built previously and bind it to the vaultusers group:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault write auth/ldap/groups/vaultusers policies=app-reader</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Let’s log in and test our access from the CLI. We’ll make sure we have our server location set in the environment first:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ export VAULT_ADDR=https://vault.example.com:8200/</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Now we log in with username/password:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault login -method=ldap username=ansible<br /></code></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>Password (will be hidden):</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>Success! You are now authenticated. The token information displayed below<br /></code></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>is already stored in the token helper. You do NOT need to run "vault login"</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>again. Future Vault requests will automatically use this token. </code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>Key                    Value</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>---                    -----</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>token                  hvs.CAESICz0NC0UNUTW1nyxyxyxyxy</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>token_accessor         jXIisU1vaHRGRkxyxyxyxy</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>token_duration         768h</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>token_renewable        true</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>token_policies         ["app-reader" "default"]</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>identity_policies      []</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>policies               ["app-reader" "default"]</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>token_meta_username    ansible</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Since ‘ansible’ is a member of the ‘vaultusers’ security group in AD, you can see that we have the “app-reader” policy applied (in addition to default). So let’s see if we can read our vcenter credentials:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ vault kv get apps/vmware</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>== Secret Path ==</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>apps/data/vmware</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>======= Metadata =======</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>Key                Value</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>---                -----</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>created_time       2022-12-13T22:16:24.625488264Z</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>custom_metadata    </code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>deletion_time      n/a</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>destroyed          false</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>version            3</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>========== Data ==========</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>Key                 Value</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>---                 -----</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_password    SomeVerySecretPassword</code><br /></strong></span><span style="font-family: arial, helvetica, sans-serif;"><strong><code>vcenter_username    administrator@vsphere.local</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Success!</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">To use username and password credentials in our playbook, instead of setting a token in an environment variable we set our username and password instead:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ export ANSIBLE_HASHI_VAULT_USERNAME="ansible"</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code>$ export ANSIBLE_HASHI_VAULT_PASSWORD="YouWontEverGuessIt"</code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><strong><code></code></strong></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">We also need to change the line in our vars.yml to specify ldap instead of token auth:</span></p>
<p style="font-weight: 400;"> </p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code><strong>ansible_hashi_vault_auth_method: ldap</strong></code></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;"><code></code></span></p>
<p style="font-weight: 400;"><span style="font-family: arial, helvetica, sans-serif;">Now our playbook will run using username/password against ldap instead of requiring a token.</span></p>
<p style="font-weight: 400;"> </p><div class="item_footer"><p><small><a href="https://george.bike/?p=92&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=92&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=92</wfw:commentRss>
		</item>
				<item>
			<title>Update Unifi Dream Machine Pro certificates with automation</title>
			<link>https://george.bike/?p=91&amp;more=1</link>
			<pubDate>Thu, 27 Oct 2022 18:50:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Linux</category>			<guid isPermaLink="false">91@https://george.bike/</guid>
						<description>&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Since I like to use Letsencrypt for my certificates I wanted to have a method to deploy them and keep them up to date on my Unifi Dream Machine Pro. I did some reading and found that the certs are actually in two different places, one for the web GUI and one for the WIFI guest portal.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;I used some shell scripting along with make, ansible and a few cron jobs to get it done.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;The files that need to be maintained on the UDM Pro are these:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;/mnt/data/unifi-os/unifi/data/keystore&lt;/code&gt; - this is a java keystore file&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;/mnt/data/unifi-os/unifi-core/config/unifi-core.crt&lt;/code&gt; - full chain certificate in PEM format&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;/mnt/data/unifi-os/unifi-core/config/unifi-core.key&lt;/code&gt; - key for the PEM cert&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;I have all my certificate renewals done on a single VM which is much easier to manage than having each server do one. So first step I needed was to copy the certificates to a location that my ansible user could read them when there was a renewal. (they are only accessible by root otherwise). Fortunately, certbot has a hook that can be used to do this. I modified my certbot renewal file in /etc/letsencrypt/renewal/mydomain.com and added a line for the hook:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;[renewalparams]&lt;br /&gt;authenticator = dns-rfc2136&lt;br /&gt;account = 656f748e58bf73c472623f243ab7eda1&lt;br /&gt;server = https://acme-v02.api.letsencrypt.org/directory&lt;br /&gt;dns_rfc2136_credentials = /etc/letsencrypt/certbot-rfc2136-credentials&lt;br /&gt;dns_cloudflare_propagation_seconds = 30&lt;br /&gt;dns_rfc2136_propagation_seconds = 90&lt;br /&gt;renew_hook = /usr/local/bin/copy_certs_to_ansible.sh&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Of course I have my cron set up to check and run renewals once a day.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;3&lt;/code&gt;&lt;code&gt;0 2&lt;/code&gt;&lt;code&gt; &lt;/code&gt;&lt;code&gt;*&lt;/code&gt;&lt;code&gt; * * /usr/bin/certbot renew &amp;gt;&amp;gt; /var/log/letsencrypt/renew.log&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;If the domain actually renews, certbot will execute the renew_hook which is in copy_certs_to_ansible.sh. Here is that script.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;#!/bin/sh&lt;br /&gt;#&lt;br /&gt;# Copy the pem versions to ansible certs dir&lt;br /&gt;#&lt;br /&gt;/bin/cp -p /etc/letsencrypt/live/mydomain.com/* /home/ansible/certs/mydomain.com/&lt;br /&gt;#&lt;br /&gt;# Rebuild the java keystore if needed&lt;br /&gt;#&lt;br /&gt;cd /home/ansible/certs; make&lt;br /&gt;#&lt;br /&gt;# Set proper owner and group on all the files&lt;br /&gt;#&lt;br /&gt;/bin/chown ansible /home/ansible/certs/mydomain.com/*&lt;br /&gt;/bin/chgrp ad_admins /home/ansible/certs/mydomain.com/*&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;You notice the &quot;make&quot; command in the middle. There is a Makefile in /home/ansible/certs/mydomain.com/ that manages the dependencies in order to create the java keystore file. We don&#039;t want to simply rebuild it and copy it every day because ansible will then restart the unifi-os service every time. Instead, we only want to regenerate the keystore when the certificate has actually changed. Here is the Makefile from /home/ansible/certs:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;#!/usr/bin/make&lt;br /&gt;#TZ=&quot;US/New_York&quot;&lt;br /&gt;&lt;br /&gt;all: mydomain-com-keystore&lt;br /&gt;&lt;br /&gt;mydomain-com-keystore: mydomain.com/keystore&lt;br /&gt;&lt;br /&gt;mydomain.com/keystore: mydomain.com/keystore.p12&lt;br /&gt;        @/usr/bin/keytool -importkeystore -destkeystore mydomain.com/keystore -srckeystore mydomain.com/keystore.p12 -srcstoretype PKCS12 -srcstorepass aircontrolenterprise -deststorepass aircontrolenterprise -alias unifi -noprompt&lt;br /&gt;&lt;br /&gt;mydomain.com/keystore.p12: mydomain.com/fullchain.pem mydomain.com/privkey.pem&lt;br /&gt;        @/bin/openssl pkcs12 -export -in mydomain.com/fullchain.pem -inkey mydomain.com/privkey.pem -out mydomain.com/keystore.p12 -passout pass:aircontrolenterprise -name &#039;unifi&#039;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;And finally is the ansible playbook that keeps the certificates up to date. I have the UDM Pro defined in my ansible inventory like this (udmpro.yml):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;---&lt;br /&gt;all:&lt;br /&gt;  hosts:&lt;br /&gt;  children:&lt;br /&gt;    udmpro:&lt;br /&gt;      hosts:&lt;br /&gt;        gw.mydomain.com:&lt;br /&gt;          ansible_connection: ssh&lt;br /&gt;          ansible_user: &quot;root&quot;&lt;br /&gt;          ansible_ssh_pass: &quot;yourrootpassword&quot;&lt;br /&gt;          ansible_ssh_private_key_file: &quot;~/.ssh/id_rsa.pub&quot;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Here is the playbook that logs into the UDM Pro and checks to make sure certificates are up to date, restarts unifi-os if needed (udmpro_update.yml).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;---&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;- hosts: udmpro&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;  gather_facts: no&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;  become: no&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;  tasks:&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;    - name: Copy *.mydomain.com certificate file&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;      ansible.builtin.copy:&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        src: /home/ansible/certs/mydomain.com/fullchain.pem&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        dest: /mnt/data/unifi-os/unifi-core/config/unifi-core.crt&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        owner: root&lt;br /&gt;&lt;/code&gt;&lt;code&gt;         group: root&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        mode: &#039;0644&#039;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        backup: true&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;      register: cert&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;    - name: Copy *.mydomain.com key file&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;      ansible.builtin.copy:&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        src: /home/ansible/certs/mydomain.com/privkey.pem&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        dest: /mnt/data/unifi-os/unifi-core/config/unifi-core.key&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        owner: root&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        group: root&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        mode: &#039;0644&#039;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        backup: true&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;      register: key&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;    - name: Copy java keystore&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;      ansible.builtin.copy:&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        src: /home/ansible/certs/mydomain.com/keystore&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        dest: /mnt/data/unifi-os/unifi/data/keystore&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        owner: 902&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        group: 902&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        mode: &#039;0640&#039;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;        backup: true&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;      register: keystore&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;- name: Restart unifi-os if needed&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;command: unifi-os restart&lt;br /&gt;&lt;/code&gt;&lt;code&gt;when: cert.changed or key.changed or keystore.changed&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;That playbook is called via cron once per day and makes sure the most recent letsencrypt certificate is installed on the UDM Pro.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=91&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p><span style="font-size: 12pt;">Since I like to use Letsencrypt for my certificates I wanted to have a method to deploy them and keep them up to date on my Unifi Dream Machine Pro. I did some reading and found that the certs are actually in two different places, one for the web GUI and one for the WIFI guest portal.</span></p>
<p><span style="font-size: 12pt;">I used some shell scripting along with make, ansible and a few cron jobs to get it done.</span></p>
<p><span style="font-size: 12pt;">The files that need to be maintained on the UDM Pro are these:</span><br /><br /></p>
<p><span style="font-size: 12pt;"><code>/mnt/data/unifi-os/unifi/data/keystore</code> - this is a java keystore file</span><br /><span style="font-size: 12pt;"><code>/mnt/data/unifi-os/unifi-core/config/unifi-core.crt</code> - full chain certificate in PEM format</span><br /><span style="font-size: 12pt;"><code>/mnt/data/unifi-os/unifi-core/config/unifi-core.key</code> - key for the PEM cert</span></p>
<p> </p>
<p><span style="font-size: 12pt;">I have all my certificate renewals done on a single VM which is much easier to manage than having each server do one. So first step I needed was to copy the certificates to a location that my ansible user could read them when there was a renewal. (they are only accessible by root otherwise). Fortunately, certbot has a hook that can be used to do this. I modified my certbot renewal file in /etc/letsencrypt/renewal/mydomain.com and added a line for the hook:</span><br /><br /></p>
<p><span style="font-size: 12pt;"><code>[renewalparams]<br />authenticator = dns-rfc2136<br />account = 656f748e58bf73c472623f243ab7eda1<br />server = https://acme-v02.api.letsencrypt.org/directory<br />dns_rfc2136_credentials = /etc/letsencrypt/certbot-rfc2136-credentials<br />dns_cloudflare_propagation_seconds = 30<br />dns_rfc2136_propagation_seconds = 90<br />renew_hook = /usr/local/bin/copy_certs_to_ansible.sh<br /><br /></code></span></p>
<p><span style="font-size: 12pt;">Of course I have my cron set up to check and run renewals once a day.</span><br /><br /></p>
<p style="text-align: left;"><span style="font-size: 12pt;"><code>3</code><code>0 2</code><code> </code><code>*</code><code> * * /usr/bin/certbot renew &gt;&gt; /var/log/letsencrypt/renew.log<br /><br /></code><code></code></span></p>
<p><span style="font-size: 12pt;">If the domain actually renews, certbot will execute the renew_hook which is in copy_certs_to_ansible.sh. Here is that script.</span><br /><br /></p>
<p><span style="font-size: 12pt;"><code>#!/bin/sh<br />#<br /># Copy the pem versions to ansible certs dir<br />#<br />/bin/cp -p /etc/letsencrypt/live/mydomain.com/* /home/ansible/certs/mydomain.com/<br />#<br /># Rebuild the java keystore if needed<br />#<br />cd /home/ansible/certs; make<br />#<br /># Set proper owner and group on all the files<br />#<br />/bin/chown ansible /home/ansible/certs/mydomain.com/*<br />/bin/chgrp ad_admins /home/ansible/certs/mydomain.com/*<br /><br /></code></span></p>
<p><span style="font-size: 12pt;">You notice the "make" command in the middle. There is a Makefile in /home/ansible/certs/mydomain.com/ that manages the dependencies in order to create the java keystore file. We don't want to simply rebuild it and copy it every day because ansible will then restart the unifi-os service every time. Instead, we only want to regenerate the keystore when the certificate has actually changed. Here is the Makefile from /home/ansible/certs:</span><br /><br /></p>
<p style="text-align: left;"><span style="font-size: 12pt;"><code>#!/usr/bin/make<br />#TZ="US/New_York"<br /><br />all: mydomain-com-keystore<br /><br />mydomain-com-keystore: mydomain.com/keystore<br /><br />mydomain.com/keystore: mydomain.com/keystore.p12<br />        @/usr/bin/keytool -importkeystore -destkeystore mydomain.com/keystore -srckeystore mydomain.com/keystore.p12 -srcstoretype PKCS12 -srcstorepass aircontrolenterprise -deststorepass aircontrolenterprise -alias unifi -noprompt<br /><br />mydomain.com/keystore.p12: mydomain.com/fullchain.pem mydomain.com/privkey.pem<br />        @/bin/openssl pkcs12 -export -in mydomain.com/fullchain.pem -inkey mydomain.com/privkey.pem -out mydomain.com/keystore.p12 -passout pass:aircontrolenterprise -name 'unifi'<br /><br /></code></span></p>
<p><span style="font-size: 12pt;">And finally is the ansible playbook that keeps the certificates up to date. I have the UDM Pro defined in my ansible inventory like this (udmpro.yml):</span><br /><br /></p>
<p><span style="font-size: 12pt;"><code>---<br />all:<br />  hosts:<br />  children:<br />    udmpro:<br />      hosts:<br />        gw.mydomain.com:<br />          ansible_connection: ssh<br />          ansible_user: "root"<br />          ansible_ssh_pass: "yourrootpassword"<br />          ansible_ssh_private_key_file: "~/.ssh/id_rsa.pub"</code></span></p>
<p> </p>
<p><span style="font-size: 12pt;">Here is the playbook that logs into the UDM Pro and checks to make sure certificates are up to date, restarts unifi-os if needed (udmpro_update.yml).</span><br /><br /></p>
<p><span style="font-size: 12pt;"><code><code></code></code></span></p>
<p><span style="font-size: 12pt;"><code>---</code></span><br /><span style="font-size: 12pt;"><code>- hosts: udmpro</code></span><br /><span style="font-size: 12pt;"><code>  gather_facts: no</code></span><br /><span style="font-size: 12pt;"><code>  become: no</code></span></p>
<p><span style="font-size: 12pt;"><code><code></code></code></span></p>
<p><span style="font-size: 12pt;"><code>  tasks:</code></span></p>
<p><span style="font-size: 12pt;"><code><code></code></code></span></p>
<p><span style="font-size: 12pt;"><code>    - name: Copy *.mydomain.com certificate file</code></span><br /><span style="font-size: 12pt;"><code>      ansible.builtin.copy:</code></span><br /><span style="font-size: 12pt;"><code>        src: /home/ansible/certs/mydomain.com/fullchain.pem</code></span><br /><span style="font-size: 12pt;"><code>        dest: /mnt/data/unifi-os/unifi-core/config/unifi-core.crt</code></span><br /><span style="font-size: 12pt;"><code>        owner: root<br /></code><code>         group: root</code></span><br /><span style="font-size: 12pt;"><code>        mode: '0644'</code></span><br /><span style="font-size: 12pt;"><code>        backup: true</code></span><br /><span style="font-size: 12pt;"><code>      register: cert</code><code></code></span></p>
<p><span style="font-size: 12pt;"><code><code></code></code></span></p>
<p><span style="font-size: 12pt;"><code>    - name: Copy *.mydomain.com key file</code></span><br /><span style="font-size: 12pt;"><code>      ansible.builtin.copy:</code></span><br /><span style="font-size: 12pt;"><code>        src: /home/ansible/certs/mydomain.com/privkey.pem</code></span><br /><span style="font-size: 12pt;"><code>        dest: /mnt/data/unifi-os/unifi-core/config/unifi-core.key</code></span><br /><span style="font-size: 12pt;"><code>        owner: root</code></span><br /><span style="font-size: 12pt;"><code>        group: root</code></span><br /><span style="font-size: 12pt;"><code>        mode: '0644'</code></span><br /><span style="font-size: 12pt;"><code>        backup: true</code></span><br /><span style="font-size: 12pt;"><code>      register: key</code></span></p>
<p><span style="font-size: 12pt;"><code><code></code></code></span></p>
<p><span style="font-size: 12pt;"><code>    - name: Copy java keystore</code></span><br /><span style="font-size: 12pt;"><code>      ansible.builtin.copy:</code></span><br /><span style="font-size: 12pt;"><code>        src: /home/ansible/certs/mydomain.com/keystore</code></span><br /><span style="font-size: 12pt;"><code>        dest: /mnt/data/unifi-os/unifi/data/keystore</code></span><br /><span style="font-size: 12pt;"><code>        owner: 902</code></span><br /><span style="font-size: 12pt;"><code>        group: 902</code></span><br /><span style="font-size: 12pt;"><code>        mode: '0640'</code></span><br /><span style="font-size: 12pt;"><code>        backup: true</code></span><br /><span style="font-size: 12pt;"><code>      register: keystore</code></span></p>
<p><span style="font-size: 12pt;"><code><code></code></code></span></p>
<p><span style="font-size: 12pt;"><code>- name: Restart unifi-os if needed</code></span><br /><span style="font-size: 12pt;"><code>command: unifi-os restart<br /></code><code>when: cert.changed or key.changed or keystore.changed<br /></code></span></p>
<p><span style="font-size: 12pt;"><code></code></span></p>
<p> </p>
<p><span style="font-size: 12pt;">That playbook is called via cron once per day and makes sure the most recent letsencrypt certificate is installed on the UDM Pro.</span></p>
<p> </p><div class="item_footer"><p><small><a href="https://george.bike/?p=91&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=91&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=91</wfw:commentRss>
		</item>
				<item>
			<title>MacOS - change account to admin from command line</title>
			<link>https://george.bike/?p=89&amp;more=1</link>
			<pubDate>Mon, 19 Sep 2022 07:57:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Mac</category>			<guid isPermaLink="false">89@https://george.bike/</guid>
						<description>&lt;p&gt;Had to do this today so thought I would share.....&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;&lt;span style=&quot;font-family: terminal, monaco, monospace; font-size: 12pt;&quot;&gt;dscl . -append /Groups/admin GroupMembership &amp;lt;username&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;You need to be root or use sudo.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=89&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Had to do this today so thought I would share.....</p>
<p> </p>
<pre><span style="font-family: terminal, monaco, monospace; font-size: 12pt;">dscl . -append /Groups/admin GroupMembership &lt;username&gt;</span></pre>
<p> </p>
<p>You need to be root or use sudo.</p><div class="item_footer"><p><small><a href="https://george.bike/?p=89&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=89&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=89</wfw:commentRss>
		</item>
				<item>
			<title>Create a RAID 10 on Mac OS (Monterey)</title>
			<link>https://george.bike/?p=88&amp;more=1</link>
			<pubDate>Sun, 31 Jul 2022 21:27:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Mac</category>			<guid isPermaLink="false">88@https://george.bike/</guid>
						<description>&lt;p&gt;I had four WD RED 4TB drives and wanted to get better performance out of them with a mirror but also wanted the ability to replace a drive if (when) one failed.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Indications from online searching said I could create either a RAID 10 or 0-1. I&#039;m not sure if one is better than the other. I went with the 10 configuration since I&#039;m already familiar with that on my TrueNAS.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Trying to do this from the Disk Utility always failed with an error message saying the RAID couldn&#039;t be created. The only type of array I was able to create out of two mirrored pairs of drives was a concatenated array. That still gave errors but appeared to have worked. But that&#039;s not going to give me any performance benefit.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Instead, the solution is to do everything from the command line. So here we go....&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;By the way, my disks are in an external cabinet attached via Thunderbolt 3.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The four disks are disk2, disk5, disk6, and disk7 (use &#039;&lt;span style=&quot;font-family: terminal, monaco, monospace;&quot;&gt;diskutil list&lt;/span&gt;&#039; to find yours). Make sure you get the correct disks as they will be repartitioned and reformatted.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Let&#039;s create the first set of mirrors from disk2 and disk5. I named the set vdev0.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;font-family: terminal, monaco, monospace;&quot;&gt;# diskutil createRAID mirror vdev0 JHFS+ disk2 disk5&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Now we&#039;ll create the second set of mirrors from disk6 and disk7.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;font-family: terminal, monaco, monospace;&quot;&gt;# diskutil createRAID mirror vdev1 JHFS+ disk6 disk7&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Now do a &#039;diskutil list&#039; and find the disk numbers of the newly created mirrors. Mine were disk8 and disk10.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Finally, create the striped set of mirrors. I named mine WDRED.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;font-family: terminal, monaco, monospace;&quot;&gt;# diskutil createRAID stripe WDRED JHFS+ disk8 disk10&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;That&#039;s it. if you do a diskutil AppleRAID list you&#039;ll see the two mirrors and also the striped set which should now be mounted.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=88&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>I had four WD RED 4TB drives and wanted to get better performance out of them with a mirror but also wanted the ability to replace a drive if (when) one failed.</p>
<p> </p>
<p>Indications from online searching said I could create either a RAID 10 or 0-1. I'm not sure if one is better than the other. I went with the 10 configuration since I'm already familiar with that on my TrueNAS.</p>
<p> </p>
<p>Trying to do this from the Disk Utility always failed with an error message saying the RAID couldn't be created. The only type of array I was able to create out of two mirrored pairs of drives was a concatenated array. That still gave errors but appeared to have worked. But that's not going to give me any performance benefit.</p>
<p> </p>
<p>Instead, the solution is to do everything from the command line. So here we go....</p>
<p> </p>
<p>By the way, my disks are in an external cabinet attached via Thunderbolt 3.</p>
<p> </p>
<p>The four disks are disk2, disk5, disk6, and disk7 (use '<span style="font-family: terminal, monaco, monospace;">diskutil list</span>' to find yours). Make sure you get the correct disks as they will be repartitioned and reformatted.</p>
<p> </p>
<p>Let's create the first set of mirrors from disk2 and disk5. I named the set vdev0.</p>
<p> </p>
<p><strong><span style="font-family: terminal, monaco, monospace;"># diskutil createRAID mirror vdev0 JHFS+ disk2 disk5</span></strong></p>
<p> </p>
<p>Now we'll create the second set of mirrors from disk6 and disk7.</p>
<p> </p>
<p><strong><span style="font-family: terminal, monaco, monospace;"># diskutil createRAID mirror vdev1 JHFS+ disk6 disk7</span></strong></p>
<p> </p>
<p>Now do a 'diskutil list' and find the disk numbers of the newly created mirrors. Mine were disk8 and disk10.</p>
<p> </p>
<p>Finally, create the striped set of mirrors. I named mine WDRED.</p>
<p> </p>
<p><strong><span style="font-family: terminal, monaco, monospace;"># diskutil createRAID stripe WDRED JHFS+ disk8 disk10</span></strong></p>
<p> </p>
<p>That's it. if you do a diskutil AppleRAID list you'll see the two mirrors and also the striped set which should now be mounted.</p>
<p> </p><div class="item_footer"><p><small><a href="https://george.bike/?p=88&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=88&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=88</wfw:commentRss>
		</item>
				<item>
			<title>Change Dell iDRAC system name from Linux cli</title>
			<link>https://george.bike/?p=87&amp;more=1</link>
			<pubDate>Wed, 09 Feb 2022 19:09:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Linux</category>			<guid isPermaLink="false">87@https://george.bike/</guid>
						<description>&lt;p&gt;Make sure the shell interface is enabled through the iDRAC web interface. Log in and click on iDRAC settings on the left.&lt;/p&gt;
&lt;div class=&quot;image_block&quot;&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/2022-02-11_08-55-48-1.png?mtime=1644974272&quot; rel=&quot;lightbox[p87]&quot; id=&quot;link_124&quot;&gt;&lt;img alt=&quot;Change Dell iDRAC system name from Linux cli&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/.evocache/2022-02-11_08-55-48-1.png/fit-400x320.png?mtime=1644974272&quot; width=&quot;228&quot; height=&quot;291&quot; class=&quot;loadimg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Click on the Network/Security tab.&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;div class=&quot;image_block&quot;&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/2022-02-11_08-58-36.png?mtime=1644974157&quot; rel=&quot;lightbox[p87]&quot; id=&quot;link_118&quot;&gt;&lt;img alt=&quot;Change Dell iDRAC system name from Linux cli&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/.evocache/2022-02-11_08-58-36.png/fit-400x320.png?mtime=1644974157&quot; width=&quot;400&quot; height=&quot;231&quot; class=&quot;loadimg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Scroll down and find the IPMI Settings. Make sure the Enable IPMI Over LAN box is checked.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div class=&quot;image_block&quot;&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/2022-02-11_09-00-24-2.png?mtime=1644974348&quot; rel=&quot;lightbox[p87]&quot; id=&quot;link_127&quot;&gt;&lt;img alt=&quot;Change Dell iDRAC system name from Linux cli&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/.evocache/2022-02-11_09-00-24-2.png/fit-400x320.png?mtime=1644974348&quot; width=&quot;690&quot; height=&quot;203&quot; class=&quot;loadimg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Install ipmitool on another device or your workstation, so for Ubuntu 20.04 I used:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;apt install ipmitool&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Convert the name you want to set into hex values. For that used:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;echo &quot;new-hostname&quot; | od -A n -t x1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;That will output the string as hex digits.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Then you use the ipmitool command like this:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;ipmitool -H &amp;lt;ip-address-of-dell-host&amp;gt; -U &amp;lt;username&amp;gt; -P &amp;lt;password&amp;gt; -I lanplus raw &lt;span style=&quot;color: #00ff00;&quot;&gt;0x06 0x58 0x02 0x00 0x05&lt;/span&gt; &lt;span style=&quot;color: #ff6600;&quot;&gt;0x0d&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;0x6e 0x65 0x77 0x2d 0x68 0x6f 0x73 0x74 0x6e 0x61 0x6d 0x65 0x0a&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;span style=&quot;color: #00ff00;&quot;&gt;0x06 0x58 0x02 0x00 0x05 &lt;span style=&quot;color: #000000;&quot;&gt;- this addresses the correct variable in the iDRAC, always the same.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ff6600;&quot;&gt;0x0d &lt;span style=&quot;color: #000000;&quot;&gt;- this is the number of bytes in the new hostname, in this case 13, in hex.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ff6600;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0x6e 0x65 0x77 0x2d 0x68 0x6f 0x73 0x74 0x6e 0x61 0x6d 0x65 0x0a &lt;span style=&quot;color: #000000;&quot;&gt;- this is the hostname characters coded in hex from previous step.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;The example above therefore sets the system name to &quot;new-hostname&quot;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=87&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Make sure the shell interface is enabled through the iDRAC web interface. Log in and click on iDRAC settings on the left.</p>
<div><a href="https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/2022-02-11_08-55-48-1.png?mtime=1644974272" rel="lightbox[p87]" id="link_124"><img alt="Change Dell iDRAC system name from Linux cli" src="https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/.evocache/2022-02-11_08-55-48-1.png/fit-320x320.png?mtime=1644974272" width="228" height="291" class="loadimg" /></a></div>
<p> </p>
<p>Click on the Network/Security tab.</p>
<p><img /></p>
<div><a href="https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/2022-02-11_08-58-36.png?mtime=1644974157" rel="lightbox[p87]" id="link_118"><img alt="Change Dell iDRAC system name from Linux cli" src="https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/.evocache/2022-02-11_08-58-36.png/fit-320x320.png?mtime=1644974157" width="400" height="231" class="loadimg" /></a></div>
<p>Scroll down and find the IPMI Settings. Make sure the Enable IPMI Over LAN box is checked.</p>
<p> </p>
<div><a href="https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/2022-02-11_09-00-24-2.png?mtime=1644974348" rel="lightbox[p87]" id="link_127"><img alt="Change Dell iDRAC system name from Linux cli" src="https://george.bike/media/blogs/george/quick-uploads/change-dell-idrac-system-name/.evocache/2022-02-11_09-00-24-2.png/fit-320x320.png?mtime=1644974348" width="690" height="203" class="loadimg" /></a></div>
<p> </p>
<p> </p>
<p>Install ipmitool on another device or your workstation, so for Ubuntu 20.04 I used:</p>
<p> </p>
<p><code>apt install ipmitool</code></p>
<p> </p>
<p>Convert the name you want to set into hex values. For that used:</p>
<p> </p>
<p><code>echo "new-hostname" | od -A n -t x1</code></p>
<p> </p>
<p>That will output the string as hex digits.</p>
<p> </p>
<p>Then you use the ipmitool command like this:</p>
<p> </p>
<p><code>ipmitool -H &lt;ip-address-of-dell-host&gt; -U &lt;username&gt; -P &lt;password&gt; -I lanplus raw <span style="color: #00ff00;">0x06 0x58 0x02 0x00 0x05</span> <span style="color: #ff6600;">0x0d</span> <span style="color: #0000ff;">0x6e 0x65 0x77 0x2d 0x68 0x6f 0x73 0x74 0x6e 0x61 0x6d 0x65 0x0a</span></code></p>
<p> </p>
<p><span style="color: #0000ff;"><span style="color: #00ff00;">0x06 0x58 0x02 0x00 0x05 <span style="color: #000000;">- this addresses the correct variable in the iDRAC, always the same.</span></span></span></p>
<p><span style="color: #ff6600;">0x0d <span style="color: #000000;">- this is the number of bytes in the new hostname, in this case 13, in hex.</span></span></p>
<p><span style="color: #ff6600;"><span style="color: #0000ff;">0x6e 0x65 0x77 0x2d 0x68 0x6f 0x73 0x74 0x6e 0x61 0x6d 0x65 0x0a <span style="color: #000000;">- this is the hostname characters coded in hex from previous step.</span></span></span></p>
<p> </p>
<p><span style="color: #000000;">The example above therefore sets the system name to "new-hostname".</span></p>
<p> </p><div class="item_footer"><p><small><a href="https://george.bike/?p=87&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=87&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=87</wfw:commentRss>
		</item>
				<item>
			<title>Use Letsencrypt certs on Postfix and Dovecot with selinux</title>
			<link>https://george.bike/?p=86&amp;more=1</link>
			<pubDate>Wed, 07 Apr 2021 16:54:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Linux</category>			<guid isPermaLink="false">86@https://george.bike/</guid>
						<description>&lt;p&gt;I have my certificates mounted via NFS on all hosts so that it gives me easy access to them for services that use SSL. The workaround I was using for mail services was to mount like this (from /etc/fstab):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;10.20.40.13:/mnt/tank/unix/web/letsencrypt /etc/letsencrypt nfs ro,context=&quot;system_u:object_r:postfix_etc_t:s0&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That solves the issue of context for selinux so that postfix can read the files. The issue is that I can&#039;t read those same files with dovecot. I had a cron going to copy the certs to /etc/dovecot dir but that was a bit of a hack. So today I dug into the issue and fixed it.&lt;/p&gt;
&lt;p&gt;The solution is to add to the current selinux policy so that dovecot can essentially read postfix&#039;s files. I suppose it is slightly less secure that way but since they are both part of the mail system I think it&#039;s an acceptable risk.&lt;/p&gt;
&lt;p&gt;So here is the TE file that I eventually ended up with that allowed dovecot to start successfully. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;module dovecot_read_postfix 1.0;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;require {&lt;br /&gt;type postfix_etc_t;&lt;br /&gt;type init_t;&lt;br /&gt;type unconfined_service_t;&lt;br /&gt;type dovecot_t;&lt;br /&gt;class process siginh;&lt;br /&gt;class filesystem remount;&lt;br /&gt;class dir search;&lt;br /&gt;class file { open read };&lt;br /&gt;class lnk_file read;&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;#============= dovecot_t ==============&lt;br /&gt;allow dovecot_t postfix_etc_t:dir search;&lt;br /&gt;allow dovecot_t postfix_etc_t:file { open read};&lt;br /&gt;allow dovecot_t postfix_etc_t:lnk_file read;&lt;br /&gt;#============= init_t ==============&lt;br /&gt;allow init_t postfix_etc_t:filesystem remount;&lt;br /&gt;allow init_t unconfined_service_t:process siginh;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=86&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>I have my certificates mounted via NFS on all hosts so that it gives me easy access to them for services that use SSL. The workaround I was using for mail services was to mount like this (from /etc/fstab):</p>
<p><code>10.20.40.13:/mnt/tank/unix/web/letsencrypt /etc/letsencrypt nfs ro,context="system_u:object_r:postfix_etc_t:s0"</code></p>
<p>That solves the issue of context for selinux so that postfix can read the files. The issue is that I can't read those same files with dovecot. I had a cron going to copy the certs to /etc/dovecot dir but that was a bit of a hack. So today I dug into the issue and fixed it.</p>
<p>The solution is to add to the current selinux policy so that dovecot can essentially read postfix's files. I suppose it is slightly less secure that way but since they are both part of the mail system I think it's an acceptable risk.</p>
<p>So here is the TE file that I eventually ended up with that allowed dovecot to start successfully. </p>
<p><code></code></p>
<p> </p>
<p><code></code></p>
<p> </p>
<p><code></code></p>
<p>module dovecot_read_postfix 1.0;</p>
<p><code></code></p>
<p>require {<br />type postfix_etc_t;<br />type init_t;<br />type unconfined_service_t;<br />type dovecot_t;<br />class process siginh;<br />class filesystem remount;<br />class dir search;<br />class file { open read };<br />class lnk_file read;<br />}</p>
<p><code></code></p>
<p>#============= dovecot_t ==============<br />allow dovecot_t postfix_etc_t:dir search;<br />allow dovecot_t postfix_etc_t:file { open read};<br />allow dovecot_t postfix_etc_t:lnk_file read;<br />#============= init_t ==============<br />allow init_t postfix_etc_t:filesystem remount;<br />allow init_t unconfined_service_t:process siginh;</p>
<p><code></code></p>
<p> </p>
<p><code></code></p>
<p> </p>
<p><code></code></p><div class="item_footer"><p><small><a href="https://george.bike/?p=86&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=86&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=86</wfw:commentRss>
		</item>
				<item>
			<title>Freebie gift almost causes catastrophe</title>
			<link>https://george.bike/?p=85&amp;more=1</link>
			<pubDate>Wed, 16 Sep 2020 09:05:00 +0000</pubDate>			<dc:creator>George</dc:creator>
			<category domain="main">Mac</category>			<guid isPermaLink="false">85@https://george.bike/</guid>
						<description>&lt;p&gt;When I renewed my Wired subscription I don&#039;t remember reading that I would receive a promotional gift. So it was a pleasant surprise to see an unexpected envelope in the mail. That was, until I opened it.&lt;/p&gt;
&lt;p&gt;Inside was a battery power pack complete with charging cable. Looking at it casually, it seemed a bit deformed. After opening it I saw that the battery inside had expanded to the point that it broke the plastic outer housing.&lt;/p&gt;
&lt;div class=&quot;image_block&quot;&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/img_2799.jpeg?mtime=1600268051&quot; rel=&quot;lightbox[p85]&quot; id=&quot;link_114&quot;&gt;&lt;img alt=&quot;Freebie gift almost causes catastrophe&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/.evocache/img_2799.jpeg/fit-400x320.jpeg?mtime=1600268051&quot; width=&quot;400&quot; height=&quot;300&quot; class=&quot;loadimg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;I broke the remaining plastic apart so I could take a look at the battery itself. It was puffed up like a balloon.&lt;/p&gt;
&lt;div class=&quot;image_block&quot;&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/img_2800.jpeg?mtime=1600268059&quot; rel=&quot;lightbox[p85]&quot; id=&quot;link_115&quot;&gt;&lt;img alt=&quot;Freebie gift almost causes catastrophe&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/.evocache/img_2800.jpeg/fit-400x320.jpeg?mtime=1600268059&quot; width=&quot;400&quot; height=&quot;300&quot; class=&quot;loadimg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;image_block&quot;&gt;&lt;a href=&quot;https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/img_2801.jpeg?mtime=1600268064&quot; rel=&quot;lightbox[p85]&quot; id=&quot;link_116&quot;&gt;&lt;img alt=&quot;Freebie gift almost causes catastrophe&quot; src=&quot;https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/.evocache/img_2801.jpeg/fit-400x320.jpeg?mtime=1600268064&quot; width=&quot;400&quot; height=&quot;300&quot; class=&quot;loadimg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Needless to say, I&#039;m glad this stupid little thing didn&#039;t explode in my face or burn down my house. If I&#039;m reading the data code correctly, this battery was made two years ago. I&#039;m going to do some additional testing to see if I can determine exactly what went wrong.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://george.bike/?p=85&amp;amp;more=1&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>When I renewed my Wired subscription I don't remember reading that I would receive a promotional gift. So it was a pleasant surprise to see an unexpected envelope in the mail. That was, until I opened it.</p>
<p>Inside was a battery power pack complete with charging cable. Looking at it casually, it seemed a bit deformed. After opening it I saw that the battery inside had expanded to the point that it broke the plastic outer housing.</p>
<div><a href="https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/img_2799.jpeg?mtime=1600268051" rel="lightbox[p85]" id="link_114"><img alt="Freebie gift almost causes catastrophe" src="https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/.evocache/img_2799.jpeg/fit-320x320.jpeg?mtime=1600268051" width="400" height="300" class="loadimg" /></a></div>
<p>I broke the remaining plastic apart so I could take a look at the battery itself. It was puffed up like a balloon.</p>
<div><a href="https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/img_2800.jpeg?mtime=1600268059" rel="lightbox[p85]" id="link_115"><img alt="Freebie gift almost causes catastrophe" src="https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/.evocache/img_2800.jpeg/fit-320x320.jpeg?mtime=1600268059" width="400" height="300" class="loadimg" /></a></div>
<div><a href="https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/img_2801.jpeg?mtime=1600268064" rel="lightbox[p85]" id="link_116"><img alt="Freebie gift almost causes catastrophe" src="https://george.bike/media/blogs/george/quick-uploads/freebie-gift-almost-causes-catastrophe/.evocache/img_2801.jpeg/fit-320x320.jpeg?mtime=1600268064" width="400" height="300" class="loadimg" /></a></div>
<p>Needless to say, I'm glad this stupid little thing didn't explode in my face or burn down my house. If I'm reading the data code correctly, this battery was made two years ago. I'm going to do some additional testing to see if I can determine exactly what went wrong.</p>
<p> </p><div class="item_footer"><p><small><a href="https://george.bike/?p=85&amp;more=1">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>https://george.bike/?p=85&amp;more=1#comments</comments>
			<wfw:commentRss>https://george.bike/?tempskin=_rss2&#38;disp=comments&#38;p=85</wfw:commentRss>
		</item>
			</channel>
</rss>
