<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://brianshowto.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://brianshowto.com/" rel="alternate" type="text/html" /><updated>2026-01-17T17:17:31+00:00</updated><id>https://brianshowto.com/feed.xml</id><title type="html">Brian’s How To</title><subtitle>How Tos to Help You!</subtitle><author><name>Brian McCammon</name></author><entry><title type="html">Error Joining Linux to AD</title><link href="https://brianshowto.com/2026/01/17/Error-Joining-Linux-to-AD.html" rel="alternate" type="text/html" title="Error Joining Linux to AD" /><published>2026-01-17T00:00:00+00:00</published><updated>2026-01-17T00:00:00+00:00</updated><id>https://brianshowto.com/2026/01/17/Error-Joining-Linux-to-AD</id><content type="html" xml:base="https://brianshowto.com/2026/01/17/Error-Joining-Linux-to-AD.html"><![CDATA[<p>My lab has been running AD since 2002.  So I started with Windows Server 2000 and I have upgraded to every version since.  When in 2025 when I tried to join a Linux (Fedora 43 KDE) laptop to my AD I ran into an issue.  I followed the recommneded steps:</p>

<ol>
  <li>
    <p>Make sure the domain is DNS resolvable:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> brian@fedora:~$ nslookup test.local
 Server:         127.0.0.53
 Address:        127.0.0.53#53

 Non-authoritative answer:
 Name:   test.local
 Address: 192.168.122.13
</code></pre></div>    </div>
  </li>
  <li>
    <p>Set the hostname to the FQDN:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> sudo hostnamectl set-hostname fedora.test.local
</code></pre></div>    </div>
  </li>
  <li>
    <p>Finally the problem command:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> brian@fedora:~$ sudo realm join test.local -v
 * Resolving: _ldap._tcp.test.local
 * Performing LDAP DSE lookup on: 192.168.122.13
 * Successfully discovered: Test.local
 realm: Couldn't authenticate as Administrator@TEST.LOCAL: KDC has no support for encryption type 
</code></pre></div>    </div>
  </li>
</ol>

<p>I went down the rabbit hole of all the things that could cause the issue, from not having the LDAPS cert trusted, editing the krb5.conf to GPO to set the Kerberos encryption types.  The actuall solution was easier than all of that.  In AD I had to go to the user I was using to join the domain and check both:</p>

<p>“This account supports Kerberos AES 128 bit encryption.”<br />
“This account supports Kerberos AES 256 bit encryption.”</p>

<p><img src="/assets/images/AD-User-Settings.png" alt="User Settings" /></p>

<p>The next important step after that is to change the password.  The password can bet set to the same or different but it must be reset.</p>

<p>Try to run the join command again and:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brian@fedora:~$ sudo realm join test.local -v
* Resolving: _ldap._tcp.test.local
* Performing LDAP DSE lookup on: 192.168.122.13
* Successfully discovered: Test.local
Password for Administrator@TEST.LOCAL:  
* Couldn't find file: /usr/sbin/oddjobd
* Required files: /usr/sbin/sssd, /usr/sbin/oddjobd, /usr/libexec/oddjob/mkhomedir, /usr/libexec/sssd/gpo_child, /usr/sbin/adcli
* Resolving required packages
* Installing necessary packages: oddjob oddjob-mkhomedir adcli sssd-ad
* LANG=C /usr/sbin/adcli join --verbose --domain Test.local --domain-realm TEST.LOCAL --domain-controller 192.168.122.13 --login-type user --login-ccache=/
var/cache/realmd/realm-ad-kerberos-FE07I3
* Using domain name: Test.local
* Calculated computer account name from fqdn: FEDORA
* Using domain realm: Test.local
* Sending NetLogon ping to domain controller: 192.168.122.13
* Received NetLogon info from: AD03.Test.local
* Wrote out krb5.conf snippet to /var/cache/realmd/adcli-krb5-hZZg26/krb5.d/adcli-krb5-conf-w8sK5K
* Using GSS-SPNEGO for SASL bind
* Looked up short domain name: TEST
* Looked up domain SID: S-1-5-21-2613415956-2557402697-1370877112
* Received NetLogon info from: AD03.Test.local
* Using fully qualified name: fedora.test.local
* Using domain name: Test.local
* Using computer account name: FEDORA
* Using domain realm: Test.local
* Calculated computer account name from fqdn: FEDORA
* Generated 120 character computer password
* Using keytab: FILE:/etc/krb5.keytab
* A computer account for FEDORA$ does not exist
* Found well known computer container at: CN=Computers,DC=Test,DC=local
* Calculated computer account: CN=FEDORA,CN=Computers,DC=Test,DC=local
* Encryption type [16] not permitted.
* Encryption type [23] not permitted.
* Encryption type [3] not permitted.
* Encryption type [1] not permitted.
* Created computer account: CN=FEDORA,CN=Computers,DC=Test,DC=local
* Trying to set computer password with Kerberos
* Set computer password
* Retrieved kvno '2' for computer account in directory: CN=FEDORA,CN=Computers,DC=Test,DC=local
* Checking RestrictedKrbHost/fedora.test.local
*    Added RestrictedKrbHost/fedora.test.local
* Checking RestrictedKrbHost/FEDORA
*    Added RestrictedKrbHost/FEDORA
* Checking host/fedora.test.local
*    Added host/fedora.test.local
* Checking host/FEDORA
*    Added host/FEDORA
* Discovered which keytab salt to use
* Added the entries to the keytab: FEDORA$@TEST.LOCAL: FILE:/etc/krb5.keytab
* Added the entries to the keytab: host/FEDORA@TEST.LOCAL: FILE:/etc/krb5.keytab
* Added the entries to the keytab: host/fedora.test.local@TEST.LOCAL: FILE:/etc/krb5.keytab
* Added the entries to the keytab: RestrictedKrbHost/FEDORA@TEST.LOCAL: FILE:/etc/krb5.keytab
* Added the entries to the keytab: RestrictedKrbHost/fedora.test.local@TEST.LOCAL: FILE:/etc/krb5.keytab
* /usr/bin/systemctl enable sssd.service
* /usr/bin/systemctl restart sssd.service
* /usr/bin/sh -c /usr/bin/authselect select sssd with-mkhomedir --force &amp;&amp; /usr/bin/systemctl enable oddjobd.service &amp;&amp; /usr/bin/systemctl start oddjobd.se
rvice
Backup stored at /var/lib/authselect/backups/2026-01-17-13-54-04.liSrxD
Profile "sssd" was selected.

Make sure that SSSD service is configured and enabled. See SSSD documentation for more information.
 
- with-mkhomedir is selected, make sure pam_oddjob_mkhomedir module
 is present and oddjobd service is enabled and active
 - systemctl enable --now oddjobd.service

Created symlink '/etc/systemd/system/multi-user.target.wants/oddjobd.service' → '/usr/lib/systemd/system/oddjobd.service'.
* Successfully enrolled machine in realm
</code></pre></div></div>

<p>The laptop is now joined to the AD domain.</p>

<p>Just some tips:</p>
<ul>
  <li>Enable oodjob service
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  systemctl enable --now oddjobd.service
</code></pre></div>    </div>
  </li>
  <li>The user name will be in the format user@Domain.local.  In my example it would be administrator@Test.local.  As always Linux is case sensitive.</li>
  <li>Add the user to sudoers
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  sudo usermod -aG wheel username
</code></pre></div>    </div>
  </li>
</ul>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[My lab has been running AD since 2002. So I started with Windows Server 2000 and I have upgraded to every version since. When in 2025 when I tried to join a Linux (Fedora 43 KDE) laptop to my AD I ran into an issue. I followed the recommneded steps:]]></summary></entry><entry><title type="html">Ubuntu Server Disk Resize</title><link href="https://brianshowto.com/2025/12/31/Ubuntu-Server-Disk-Resize.html" rel="alternate" type="text/html" title="Ubuntu Server Disk Resize" /><published>2025-12-31T00:00:00+00:00</published><updated>2025-12-31T00:00:00+00:00</updated><id>https://brianshowto.com/2025/12/31/Ubuntu-Server-Disk-Resize</id><content type="html" xml:base="https://brianshowto.com/2025/12/31/Ubuntu-Server-Disk-Resize.html"><![CDATA[<p>I have had the need to expand the disk on an Ubuntu Server so I thought I would lay out the steps.  First step which I won’t cover is to expand the disk, for me this is though my hypervisor.  Once the virtual disk has been expanded proceed with the following steps.</p>

<ol>
  <li>Verify the OS is seeing the drive has extra space on it
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lsblk
</code></pre></div>    </div>
    <p>Example output</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS  
 loop0                       7:0    0  55.5M  1 loop /snap/core18/2959  
 loop1                       7:1    0  55.5M  1 loop /snap/core18/2976  
 loop2                       7:2    0  63.8M  1 loop /snap/core20/2682  
 loop3                       7:3    0  63.8M  1 loop /snap/core20/2686  
 loop4                       7:4    0    74M  1 loop /snap/core22/2163  
 loop5                       7:5    0  91.4M  1 loop /snap/lxd/36558  
 loop6                       7:6    0    74M  1 loop /snap/core22/2193  
 loop7                       7:7    0  91.4M  1 loop /snap/lxd/36918  
 loop8                       7:8    0   375M  1 loop /snap/nextcloud/51274  
 loop9                       7:9    0 375.4M  1 loop /snap/nextcloud/51617  
 loop10                      7:10   0  76.6M  1 loop /snap/powershell/313  
 loop11                      7:11   0  76.6M  1 loop /snap/powershell/316  
 loop12                      7:12   0  50.8M  1 loop /snap/snapd/25202  
 loop13                      7:13   0  50.9M  1 loop /snap/snapd/25577  
 sda                         8:0    0   500G  0 disk    
 ├─sda1                      8:1    0     1G  0 part /boot/efi  
 ├─sda2                      8:2    0     2G  0 part /boot  
 └─sda3                      8:3    0 396.9G  0 part    
  └─ubuntu--vg-ubuntu--lv 252:0    0 396.9G  0 lvm  /  
 sr0                        11:0    1  1024M  0 rom     
</code></pre></div>    </div>
    <p>On device sda the size is 500G but the partitions only add up to 399.9G, so we have 100G of unpartitioned space.</p>
  </li>
  <li>Now use growpart to expand the sda3 partition
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo growpart /dev/sda 3
</code></pre></div>    </div>
    <p>Example Output</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> CHANGED: partition=3 start=6397952 old: size=832462815 end=838860766 new: size=1042178015 end=1048575966  
</code></pre></div>    </div>
    <p>It shows that partition 3 was changed to the new size.</p>
  </li>
  <li>Once the partiton has been expanded use pvresize to update the physical volume.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvresize /dev/sda3
</code></pre></div>    </div>
    <p>Example Output</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Physical volume "/dev/sda3" changed
 1 physical volume(s) resized or updated / 0 physical volume(s) not resized
</code></pre></div>    </div>
  </li>
  <li>Once the volume has been resized extend the logical volume to 100%
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv
</code></pre></div>    </div>
    <p>Example Output</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Size of logical volume ubuntu-vg/ubuntu-lv changed from &lt;396.95 GiB (101618 extents) to &lt;496.95 GiB (127218 extents).  
 Logical volume ubuntu-vg/ubuntu-lv successfully resized.  
</code></pre></div>    </div>
  </li>
  <li>Finally it’s time to grow the file system.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
</code></pre></div>    </div>
    <p>Example Output</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> resize2fs 1.47.0 (5-Feb-2023)  
 Filesystem at /dev/mapper/ubuntu--vg-ubuntu--lv is mounted on /; on-line resizing required  
 old_desc_blocks = 50, new_desc_blocks = 63  
 The filesystem on /dev/mapper/ubuntu--vg-ubuntu--lv is now 130271232 (4k) blocks long.  
</code></pre></div>    </div>
  </li>
  <li>Lastly verify the free space is being shown
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df -h
</code></pre></div>    </div>
    <p>Example Output</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Filesystem                         Size  Used Avail Use% Mounted on  
 tmpfs                              392M  988K  391M   1% /run  
 efivarfs                           128M   26K  128M   1% /sys/firmware/efi/efivars  
 /dev/mapper/ubuntu--vg-ubuntu--lv  489G  391G   78G  84% /  
 tmpfs                              2.0G     0  2.0G   0% /dev/shm  
 tmpfs                              5.0M     0  5.0M   0% /run/lock  
 /dev/sda2                          2.0G  198M  1.6G  11% /boot  
 /dev/sda1                          1.1G  6.2M  1.1G   1% /boot/efi  
 tmpfs                              392M   12K  392M   1% /run/user/1000
</code></pre></div>    </div>
    <p>On the partiton mounted as / it shows the new size of 489G.</p>
  </li>
</ol>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[I have had the need to expand the disk on an Ubuntu Server so I thought I would lay out the steps. First step which I won’t cover is to expand the disk, for me this is though my hypervisor. Once the virtual disk has been expanded proceed with the following steps.]]></summary></entry><entry><title type="html">Azure DevOps Repo to GitHub</title><link href="https://brianshowto.com/2025/12/30/DevOps-to-GitHub.html" rel="alternate" type="text/html" title="Azure DevOps Repo to GitHub" /><published>2025-12-30T00:00:00+00:00</published><updated>2025-12-30T00:00:00+00:00</updated><id>https://brianshowto.com/2025/12/30/DevOps-to-GitHub</id><content type="html" xml:base="https://brianshowto.com/2025/12/30/DevOps-to-GitHub.html"><![CDATA[<p>I currently have several private repos on Azure DevOps that I want to move to GitHub.  The easist way I could find to do it is to mirror the DevOps repo to my machine and then push it to GitHub.</p>

<p>To do this either make a directory or change directory to where you want the repo files to be.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir ~/GitTransfer
cd ~/GitTransfer
</code></pre></div></div>

<p>After the directory has been made and changed to it, mirror the DevOps repo.  I access my repos with SSH so I use the SSH for both DevOps and GitHub.  If doing this be sure to add the key first.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>eval "$(ssh-agent -s)"
ssh-add ~/.ssh/git-user

git clone --mirror &lt;SSH DevOps URL&gt;
</code></pre></div></div>

<p>This will create a directory for your repo ending in .git.  For example a repo named “Test” would create a directory called “Test.repo”  Change Directory to the repo directory.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd Test.git
</code></pre></div></div>

<p>Next add a remote shortcut for the GitHub repo to move to.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote add github &lt;SSH GitHub URL&gt;
</code></pre></div></div>

<p>Once the remote shortcut has been added then push the local mirror of the DevOps repo to the new GitHub repo.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push github --all
</code></pre></div></div>

<p>When I did this for one of my repos I got an error because at one point I had uploaded a large ISO to my DevOps repo.  Even though it was deleted the history was still there.</p>

<p>remote: fatal: pack exceeds maximum allowed size (2.00 GiB)</p>

<p>DevOps allows for large blob storage but GitHub has a hard limit at 2GB.  To find the file I had to run</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git verify-pack -v objects/pack/*.idx | sort -k3 -n | tail -20
</code></pre></div></div>

<p>This gives the top 20 largest files with the largest at the bottom, in my case it looked like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>065e9b5cfd4ccc75e446b3caad7df93e73a09a74 blob   1978372 773245 92792965 1 37d5c6babf5a2040feef3fc7f5b97e10acb3d12e
9dbf928ccb9394cdd68ee6bc08fd387f8af998c9 blob   2015618 580573 63846253
a18ccc761ce03614650f1ad6a908a443480b46c2 blob   2267763 855316 120249765 2 065e9b5cfd4ccc75e446b3caad7df93e73a09a74
7bf331c2fc0ddb7f9839c87312a83fc24e584bfd blob   3003931 903710 20099092
5c90016ed9c3c2c150bbac1fd818c549d18656a8 blob   3284480 964154 89864529
21371b1cea1bde1424bb380717b2e00d34b55218 blob   3424256 1208354 12766772
09612a22af3fd19767165bf2ace7515339092b37 blob   3571367 253466 74189236
5334c97be6d78aae6c0f3fadf4aa43ddd33a295e blob   3793920 988851 1161913
e0a99de991149555a4c6dc4b4f0461f4aa0c1ee2 blob   4233603 4213562 75660292
210a5b3fa65be4f4c226f48e56c122e8cd435d60 blob   4598784 1381434 118760208
e3c37554753da159beba1ff0006cfd4068427b6b blob   4760064 1340028 91452703
37d5c6babf5a2040feef3fc7f5b97e10acb3d12e blob   4954112 1393799 5934266
7b1205f391440eb56e7c6d0b3d6763c39de96805 blob   4965584 1583638 79958582
8548a4f2edd24fb5127a032ae697e63ef58977cc blob   5185232 1652640 72536596
53241bd1c6e62368839b76f2d5cd292306d28093 blob   5812328 1572636 2582096
4f2f00e5b9d76a825ccd4f4b1560652acf88fc5f blob   9824256 2241841 95668301
b3e575a85a40e42c264b8cf400c8eb0beeef6d8a blob   12961280 3186540 7328065
07c99d5cc89a49ab84ba22a03dae45fca6cf8449 blob   14496025 637491 4154732
412cbe95c80b356d3481aec126197068297a6f52 blob   20437257 20404808 97910464
3d1a29d89fe06d11035c66b9978972a055e1db02 blob   2716784640 2189153983 121189846
</code></pre></div></div>

<p>The last one was about 2.5GB so to find what file that is I had to run</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git rev-list --objects --all | grep 3d1a29d89fe06d11035c66b9978972a055e1db02
</code></pre></div></div>

<p>That returned</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>3d1a29d89fe06d11035c66b9978972a055e1db02 en_sql_server_2016_standard_with_service_pack_1_x64_dvd_9540929.iso
</code></pre></div></div>

<p>So now I know the offending file.  I had to rewrite the history to remove the old ISO.  I am running Fedora KDE so I needed to install git-filter-repo</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo dnf install git-filter-repo
</code></pre></div></div>

<p>If attempting this on Windows then Python will need to be installed and then git-filter-repo can be installed via pip</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install git-filter-repo
</code></pre></div></div>

<p>Once git-filter-repo was installed I could remove all traces of the ISO from the commit history with the command</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git filter-repo --path en_sql_server_2016_standard_with_service_pack_1_x64_dvd_9540929.iso --invert-paths --force
</code></pre></div></div>

<p>After that I cleaned up the logs</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git reflog expire --expire=now --all
</code></pre></div></div>

<p>Finally I was ready to try pushing the local mirror of the DevOps repo to GitHub again.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push github --all
</code></pre></div></div>

<p>Success!!!</p>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[I currently have several private repos on Azure DevOps that I want to move to GitHub. The easist way I could find to do it is to mirror the DevOps repo to my machine and then push it to GitHub.]]></summary></entry><entry><title type="html">RDCMan Change Passwords with PowerShell</title><link href="https://brianshowto.com/2024/03/03/RDCMan-Change-Passwords-with-PowerShell.html" rel="alternate" type="text/html" title="RDCMan Change Passwords with PowerShell" /><published>2024-03-03T00:00:00+00:00</published><updated>2024-03-03T00:00:00+00:00</updated><id>https://brianshowto.com/2024/03/03/RDCMan-Change-Passwords-with-PowerShell</id><content type="html" xml:base="https://brianshowto.com/2024/03/03/RDCMan-Change-Passwords-with-PowerShell.html"><![CDATA[<p>I have been using different RDP managers over the years and the last one I was using was Terminals. but the project has not been supported since 2019 and so security issues that come up will never be fixed. I recently moved to a different laptop and decided it was time to look for a different RDP manager. I landed on RDCMan from Sysinternals.</p>

<p>One of the things I like a lot is that I can encrypt the passwords using a cert instead of it being tied to my user and computer. That way I can have it on multiple computers and its always up to date, because I sync the config via OneDrive</p>

<p>The issue I ran into was our PAM solution has a unique username string for every server. RDCMan does not have a feature that will allow you to change just the password to everything in the group. So I started to look into solutions for this. I came across a few GitHub RDCMan Password cracking projects and decided that if they could use PowerShell to decrypt the passwords then I could use PowerShell to encrypt password then replace them in the cfg file.</p>

<p>I was surprised to find out that to get the methods for RDCMan all that I had to do was to rename the RDCMan.exe to RDCMan.dll and import the DLL like a module. So I started out with a variable with the path to my RDCMan.exe and then did a copy and then imported it.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$RDCManPath = "C:\Program Files\RDCMan\RDCMan.exe"
Copy-Item -Path $RDCManPath -Destination "$env:TEMP\RDCMan.dll" -Force
Import-Module "$env:TEMP\RDCMan.dll"
</code></pre></div></div>

<p>Once I had that I could encrypt the password with the cert. I just needed the cert thumbprint, create a new object, set the encryption settings and encrypt the password.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$Password = "Password1234"
$EncryptionSettings = New-Object -TypeName RdcMan.EncryptionSettings
$EncryptionSettings.EncryptionMethod.Value = 'Certificate'
If ([string]::IsNullOrEmpty($CertThumbprint))
{
    $CertThumbprint = (Get-ChildItem Cert:\CurrentUser\My | Out-GridView -Title "Select Cert for RDC Encryption" -PassThru).Thumbprint
}
$EncryptionSettings.CredentialData.Value = $CertThumbprint

$RDCEncPass = [RdcMan.Encryption]::EncryptString($Password,$EncryptionSettings)
</code></pre></div></div>

<p>Perfect, now I have a password that was encrypted with our cert that can be added to my cfg file. I just need to find the existing passwords and replace them. To do that I need to import the cfg file as XML then I can get the existing entries under my PAM group that the password is not inherited. Then once all the entries are updated I just write the XML back</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$RDGPath = "C:\Users\User\Documents\RDC.rdg"

$XML = [xml](Get-Content -Path $RDGPath) 

$NeedsChanged = ($XML.RDCMan.file.group | Where-Object {$_.properties.name -eq "PAM"}).group.server.logonCredentials | Where-Object {$_.inherit -eq "none"}
ForEach ($Change in $NeedsChanged)
{
    $Change.password = $RDCEncPass
}

$XML.OuterXml | Set-Content $RDGPath
</code></pre></div></div>

<p>That’s the basics of the script but to make things more secure I wanted to prompt for the password as a secure string and then convert it to plain text so it can be encrypted by RDCMan.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$Password = Read-Host "Enter new password" -AsSecureString
$Password = [Net.NetworkCredential]::new('', $Password).Password
</code></pre></div></div>

<p>Other things I wanted to add to make this more versatile are variable for the cert thumbprint, file picker for RDCMan.exe, cfg and an Out-GridView for when the variables are not set. After all that was done here is the full script.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$RDCManPath = ""
$RDGPath = ""
$CertThumbprint = ""

$Password = Read-Host "Enter new password" -AsSecureString
$Password = [Net.NetworkCredential]::new('', $Password).Password

If (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {$_.Location -like "*RDCMan.dll"}))
{
    If ([string]::IsNullOrEmpty($RDCManPath))
    {
        Add-Type -AssemblyName System.Windows.Forms
        Write-Host "Select the RDCMan.exe from the File Browser dialog box"
        $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
            InitialDirectory = [Environment]::GetFolderPath('Desktop') 
            Filter = 'EXE |*.exe'
        }
        $null = $FileBrowser.ShowDialog()
        $RDCManPath = $FileBrowser.FileName
    }
    Copy-Item -Path $RDCManPath -Destination "$env:TEMP\RDCMan.dll" -Force
    Import-Module "$env:TEMP\RDCMan.dll"
}
$EncryptionSettings = New-Object -TypeName RdcMan.EncryptionSettings
$EncryptionSettings.EncryptionMethod.Value = 'Certificate'
If ([string]::IsNullOrEmpty($CertThumbprint))
{
    $CertThumbprint = (Get-ChildItem Cert:\CurrentUser\My | Out-GridView -Title "Select Cert for RDC Encryption" -PassThru).Thumbprint
}
$EncryptionSettings.CredentialData.Value = $CertThumbprint

$RDCEncPass = [RdcMan.Encryption]::EncryptString($Password,$EncryptionSettings)

If ([string]::IsNullOrEmpty($RDGPath))
{
    Add-Type -AssemblyName System.Windows.Forms
    Write-Host "Select the RDG file to update from the File Browser dialog box"
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
        InitialDirectory = [Environment]::GetFolderPath('Desktop') 
        Filter = 'RDG |*.rdg'
    }
    $null = $FileBrowser.ShowDialog()
    $RDGPath = $FileBrowser.FileName
}

$XML = [xml](Get-Content -Path $RDGPath) 

$NeedsChanged = ($XML.RDCMan.file.group | Where-Object {$_.properties.name -eq "PAM"}).group.server.logonCredentials | Where-Object {$_.inherit -eq "none"}
ForEach ($Change in $NeedsChanged)
{
    $Change.password = $RDCEncPass
}

$XML.OuterXml | Set-Content $RDGPath

Write-Host "$RDGPath PAM group servers has been updated with new password"
</code></pre></div></div>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[I have been using different RDP managers over the years and the last one I was using was Terminals. but the project has not been supported since 2019 and so security issues that come up will never be fixed. I recently moved to a different laptop and decided it was time to look for a different RDP manager. I landed on RDCMan from Sysinternals.]]></summary></entry><entry><title type="html">PowerShell Universal Dashboard – Update Page On Button Click</title><link href="https://brianshowto.com/2020/08/25/PowerShell-Univeral-Dashboard-Update-Page-on-Button-Click.html" rel="alternate" type="text/html" title="PowerShell Universal Dashboard – Update Page On Button Click" /><published>2020-08-25T00:00:00+00:00</published><updated>2020-08-25T00:00:00+00:00</updated><id>https://brianshowto.com/2020/08/25/PowerShell-Univeral-Dashboard-Update-Page-on-Button-Click</id><content type="html" xml:base="https://brianshowto.com/2020/08/25/PowerShell-Univeral-Dashboard-Update-Page-on-Button-Click.html"><![CDATA[<p>I have recently gotten into working with PowerShell Universal Dashboard. At work we have some requirements that Universal Dashboard will help accommodate. So I got to work with the community edition to be able to do a proof of concept. Everything has gone very well and we are purchasing the suite. That being said the biggest issue I ran into was being able to update the page with results by pushing a button.</p>

<p>I knew that I wanted to create a new UDCard to display the information but I could not get it to display. That is when I figured out that I had to have a place holder UDElement and then once I had the UDCard I could just replace the place holder UDElement with the UDCard. To do this first I crated the new UDElement like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>New-UDElement -Tag "PlaceHolder" -Id "results"
</code></pre></div></div>

<p>After that in the onClick for the button I replace the place holder with the card like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Set-UDElement -Id "results" -Content {
    New-UDCard -Title "Results" -Text "Your text"
}
</code></pre></div></div>

<p>In this example I have a Dashboard that has a text box for input of a name and then a button that when pushed will display a message in a new card.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#Get the existing running Dashboards and stop them.
Get-UDDashboard | Stop-UDDashboard

#Create the Dashboard
$Dashboard =  New-UDDashboard -Title "Test" -Content {
    #Create the text box
    New-UDTextbox -Id "txtName" -Label "Name" -Placeholder "Enter your name"
    #Create the button with onClick 
    New-UDButton -Id "btnSearch" -Text "Search" -OnClick {
        #Changes the UDElement "results" with the new UDCard
        Set-UDElement -Id "results" -Content {
            #Sets the varable Name with the value of the text box
            $Name = (Get-UDElement -Id "txtName").Attributes["value"]
            #Creates the UDCard with the title "Results" and the text "Your name is" followed by the text in the text box
            New-UDCard -Title "Results" -Text "Your name is $Name"
        }
    }
    #Place holder for the new UDCard
    New-UDElement -Tag "PlaceHolder" -Id "results"
}

#Starts the created Dashboard on port 80
Start-UDDashboard -Dashboard $Dashboard -Port 80
</code></pre></div></div>

<p>I hope this helps clarify the solution. I had a hard time finding anything about this since every example I have found just showed a UDToast and not actual output that staid on the screen.</p>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[I have recently gotten into working with PowerShell Universal Dashboard. At work we have some requirements that Universal Dashboard will help accommodate. So I got to work with the community edition to be able to do a proof of concept. Everything has gone very well and we are purchasing the suite. That being said the biggest issue I ran into was being able to update the page with results by pushing a button.]]></summary></entry><entry><title type="html">PowerShell – Create Azure Route Table with Virtual network gateway route propagation</title><link href="https://brianshowto.com/2020/02/13/PowerShell-Az-RT-Route-Propagation.html" rel="alternate" type="text/html" title="PowerShell – Create Azure Route Table with Virtual network gateway route propagation" /><published>2020-02-13T00:00:00+00:00</published><updated>2020-02-13T00:00:00+00:00</updated><id>https://brianshowto.com/2020/02/13/PowerShell-Az-RT-Route-Propagation</id><content type="html" xml:base="https://brianshowto.com/2020/02/13/PowerShell-Az-RT-Route-Propagation.html"><![CDATA[<p>Recently I was writing a script to create Azure Route Tables and I kept having issue with getting virtual network gateway route propagation to be enabled.</p>

<p>The example I was working from was:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>New-AzRouteTable -Name $RouteTableName -ResourceGroupName $ResourceGroupName -Location $Location -DisableBgpRoutePropagation
</code></pre></div></div>

<p>I was finally able to track down what was causing my issue. The DisableBgpRoutePropagation equates to disabling virtual network gateway route propagation in the Azure Portal. So the correct command to have virtual network gateway route propagation enabled is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>New-AzRouteTable -Name $RouteTableName -ResourceGroupName $ResourceGroupName -Location $Location
</code></pre></div></div>

<p>There was not a lot of information about this that I could find so I hope this helps whom ever finds it.</p>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[Recently I was writing a script to create Azure Route Tables and I kept having issue with getting virtual network gateway route propagation to be enabled.]]></summary></entry><entry><title type="html">Remove Passwords or Other Text from VSTS Git</title><link href="https://brianshowto.com/2017/11/18/Removing-Passwords-or-Other-Text-from-VSTS-Git.html" rel="alternate" type="text/html" title="Remove Passwords or Other Text from VSTS Git" /><published>2017-11-18T00:00:00+00:00</published><updated>2017-11-18T00:00:00+00:00</updated><id>https://brianshowto.com/2017/11/18/Removing-Passwords-or-Other-Text-from-VSTS-Git</id><content type="html" xml:base="https://brianshowto.com/2017/11/18/Removing-Passwords-or-Other-Text-from-VSTS-Git.html"><![CDATA[<p>In a perfect world no one would ever store usernames and passwords in code.  We are on in a perfect world and I myself make mistakes and in the past I have created scripts that required passwords in them and I accidentally pushed the code to VSTS with the password entered.  So I had to figure out how to remove that from the history of the file.  I could have deleted the project and created a new one but I would have lost all my history of commits which I did not want to do.  Here is how I found to remove text from commit history.</p>

<p>The guys at BFG Repo-Cleaner (https://rtyley.github.io/bfg-repo-cleaner/) really make this easy.  Basically you make a clone of your project in a temp folder and then you run BFG against your temp clone then you expire the reference logs and then prune them and finally push back to the project.  The steps that I use assume that you have your project name Project, you are storing the git projects at C:\Git, you have downloaded BFG to C:\Git and you have a text file which has all the text you want to replace (one phrase per line) saved to C:\Git\pass.txt   These are the exact steps I took:</p>

<ol>
  <li>Open command prompt.</li>
  <li>Make a new temp directory.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir C:\Git\TempProject
</code></pre></div>    </div>
  </li>
  <li>Change to the new directory.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd C:\Git\TempProject
</code></pre></div>    </div>
  </li>
  <li>Clone the project to the directory.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone –mirror https://yourname.visualstudio.com/_git/Project
</code></pre></div>    </div>
  </li>
  <li>Change to the Git directory.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd C:\Git
</code></pre></div>    </div>
  </li>
  <li>Run BFG with the pass.txt file against the TempProject (replace the BFG version number to match what you downloaded).
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>java -jar bfg-1.12.16.jar –replace-text pass.txt TempProject\Project.git
</code></pre></div>    </div>
  </li>
  <li>Change to the TempProject\Project.git directory.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd C:\Git\TempProject\Project.git
</code></pre></div>    </div>
  </li>
  <li>Expire and prune the reference logs.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git reflog expire –expire=now –all &amp;&amp; git gc –prune=now –aggressive
</code></pre></div>    </div>
  </li>
  <li>Push the changes back to the project.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push
</code></pre></div>    </div>
  </li>
</ol>

<p>Once you follow those steps you can go look at your commit history and the text you wanted replaced will show as <strong><em>REMOVED</em></strong>.  Now your text is safe and you can delete the temp folder that was created in step 2.</p>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[In a perfect world no one would ever store usernames and passwords in code. We are on in a perfect world and I myself make mistakes and in the past I have created scripts that required passwords in them and I accidentally pushed the code to VSTS with the password entered. So I had to figure out how to remove that from the history of the file. I could have deleted the project and created a new one but I would have lost all my history of commits which I did not want to do. Here is how I found to remove text from commit history.]]></summary></entry><entry><title type="html">Enable Secure PowerShell Remoting</title><link href="https://brianshowto.com/2017/11/06/Enable-Secure-PowerShell-Remoting.html" rel="alternate" type="text/html" title="Enable Secure PowerShell Remoting" /><published>2017-11-06T00:00:00+00:00</published><updated>2017-11-06T00:00:00+00:00</updated><id>https://brianshowto.com/2017/11/06/Enable-Secure-PowerShell-Remoting</id><content type="html" xml:base="https://brianshowto.com/2017/11/06/Enable-Secure-PowerShell-Remoting.html"><![CDATA[<p>Working with a lot of VMs in Azure it has be come more essential to be able to run my scripts on many VMs at a time.  The first step in doing this is to enable remote PowerShell and keep it secure.  Below is the script that I use to enable remote PowerShell and generate a cert to use for encrypting the communication.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#Enable PSRemoting and trust all hosts then restart the service
Enable-PSRemoting -SkipNetworkProfileCheck -Force
Set-Item WSMan:\localhost\Client\TrustedHosts -Value * -Force
Restart-Service WinRM

#Create self-signed cert
$cert = New-SelfSignedCertificate -DnsName “$env:computername” -CertStoreLocation cert:\LocalMachine\My

#Create a listener using the new cert
New-Item -Path WSMan:\Localhost\Listener -Transport HTTPS -Address * -CertificateThumbprint $cert.Thumbprint -Force

#Create an entry in Windows Firewall to allow Remote PowerShell over SSL
New-NetFirewallRule -DisplayName “WinRM – 5986” -Direction Inbound -LocalPort 5986 -Protocol TCP -Action Allow
</code></pre></div></div>

<p>Run this on both your source and destination machines.  To run a command remotely run the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#User Creds
$Domain = “DomainName”
$AdminUser = “UserName”
$AdminPass = “SuperSecretPass”

#Create secure creds
$AdminSecurePass = $AdminPass | ConvertTo-SecureString -asPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential(“$Domain\$AdminUser”,$AdminSecurePass)

#Create session options to work with the self-signed cert
$SessionOptions = New-PSSessionOption –SkipCACheck –SkipCNCheck –SkipRevocationCheck

#Run the Get-Process command on the remote server
Invoke-Command -SessionOption $SessionOptions -UseSSL -ComputerName “ServerFQDN” -Credential $Cred -ScriptBlock {Get-Process}
</code></pre></div></div>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[Working with a lot of VMs in Azure it has be come more essential to be able to run my scripts on many VMs at a time. The first step in doing this is to enable remote PowerShell and keep it secure. Below is the script that I use to enable remote PowerShell and generate a cert to use for encrypting the communication.]]></summary></entry><entry><title type="html">Visual Studio Code with Visual Studio Team Services (VSTS)</title><link href="https://brianshowto.com/2017/11/05/Visual-Studio-Code-with-VSTS.html" rel="alternate" type="text/html" title="Visual Studio Code with Visual Studio Team Services (VSTS)" /><published>2017-11-05T00:00:00+00:00</published><updated>2017-11-05T00:00:00+00:00</updated><id>https://brianshowto.com/2017/11/05/Visual-Studio-Code-with-VSTS</id><content type="html" xml:base="https://brianshowto.com/2017/11/05/Visual-Studio-Code-with-VSTS.html"><![CDATA[<p>I have been doing a ton of PowerShell scripts lately and I was wanting to find a way to tie into a version control system.  Originally I wanted to do something like GitHub but since I want to do a free option GitHub was out as everything is public on their free option.  So I looked at Visual Studio Team Services (VSTS).  They offer 5 users for free and the repositories can be setup as either git or TFS.  So VSTS was it.</p>

<p>My next challenge was PowerShell ISE.  I was wanting to interrelate VSTS into ISE but I did not find a solution that I liked but I did stuble across Visual Studio Code.  VS Code is pretty neat.  It has a ton of addons and can support many languages including PowerShell.  Also there is an addon for VSTS which is nice.</p>

<p>Now that I picked my tools I just had to get them to work together.  The information I could find left a lot to be desired.  There are articles on how to setup and create a project in VSTS.  But what now, once I had my project setup I was stuck.  So this is the reason for this post.  So to be clear right now I have Visual Studio Code installed with the VSTS addon and Git for Windows.  I also have a project setup on the VSTS site.</p>

<p>In VS Code open the Command Palette (Ctrl + Shift + P) and type:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Git: Clone
</code></pre></div></div>

<p>Enter the Repository URL which can be found on the project page on VSTS it should be something like https://yourname.visualstudio.com/_git/ProjectName.</p>

<p>Next enter the parent directory.  If you want your project to be stored at C:\git\ProjectName just enter:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C:\git
</code></pre></div></div>

<p>Once prompted to login enter the credentials to the Microsoft account that has access to the project.</p>

<p>A prompt asking to Open Repository will come up, click Open Repository.  Now that the project repository has been cloned it is time to signin to VSTS.  To do this open the Command Palette (Ctrl + Shift + P) then type:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Team: Signin
</code></pre></div></div>

<p>For ease of use select Authenticate and get an access token automatically, a code will appear so copy that and then click the link https://aka.ms/devicelog…</p>

<p>Paste the code and click continue then sign in using the credentials to the Microsoft account that has access to the project.</p>

<p>VS Code is now connected to a project repository in VSTS.  Now once any changes are made they will show up in Source Control (Ctrl + Shift + G)</p>

<p><img src="/assets/images/VSCode-SCM-300x227.jpg" alt="VSCode SCM" /></p>

<p>and the changes can be staged by clicking the plus next to the file</p>

<p><img src="/assets/images/VSCode-Stage-300x21.jpg" alt="VSCode Stage" /></p>

<p>then they can be committed by clicking the check mark at the top</p>

<p><img src="/assets/images/VSCode-Commit-300x36.jpg" alt="VSCode Commit" /></p>

<p>then sync the commits by clicking the arrows at the bottom.</p>

<p><img src="/assets/images/VSCode-Sync.jpg" alt="VSCode Sync" /></p>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[I have been doing a ton of PowerShell scripts lately and I was wanting to find a way to tie into a version control system. Originally I wanted to do something like GitHub but since I want to do a free option GitHub was out as everything is public on their free option. So I looked at Visual Studio Team Services (VSTS). They offer 5 users for free and the repositories can be setup as either git or TFS. So VSTS was it.]]></summary></entry><entry><title type="html">Snort Inline on CentOS</title><link href="https://brianshowto.com/2015/08/03/Snort-Inline-on-CentOS.html" rel="alternate" type="text/html" title="Snort Inline on CentOS" /><published>2015-08-03T00:00:00+00:00</published><updated>2015-08-03T00:00:00+00:00</updated><id>https://brianshowto.com/2015/08/03/Snort-Inline-on-CentOS</id><content type="html" xml:base="https://brianshowto.com/2015/08/03/Snort-Inline-on-CentOS.html"><![CDATA[<p>I have been wanting to setup Snort on a CentOS based firewall for a while and I finally got around to it.  The good thing is I finally got it working thanks to a blog Dennis Panagiotopoulos here, I have confirmed this works for CentOS 6.6 and 7.1.  The problem is as with getting Snort to run inline.  I was unable to find any thing on getting this to work correctly.  So here is what I had to do in addition to Dennis’s blog post:</p>

<p>First thing is to edit /etc/sysconfig/snort so it has both the internal and external interfaces like the following:</p>

<p>INTERFACE=”eth0:eth1″</p>

<p>For me this was line 15 in the file</p>

<p>Second thing is to edit /etc/snort/snort.conf uncomment the daq lines and make them like the following:</p>

<p>config daq: afpacket
config daq_dir: /usr/local/lib/daq
config daq_mode: inline
config daq_var: buffer_size_mb=128</p>

<p>For me these lines were 155 though 158 in the file.</p>

<p>The last thing I had to do was to edit the service at /etc/init.d/snort to add -Q to the end of the following lines under start like the following:</p>

<p>daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE -i $i -u $USER -g $GROUP $CONF -l $LOGDIR/$i $PASS_FIRST $BPFFILE $BPF –Q
daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE $INTERFACE -u $USER -g $GROUP $CONF -l $LOGDIR $PASS_FIRST $BPFFILE $BPF -Q</p>

<p>For me these lines were 115 and 119 in the file.</p>

<p>Once I made the changes I restarted the Snort service and then tested and confirmed Snort was running inline.</p>

<p>An easy way to test is to edit /etc/snort/rules/icmp.rules and add:</p>

<p>drop icmp any any -&gt; any any (msg:”ICMP Packet”; sid:477; rev:3;)</p>

<p>Once the rule is added restart snort and then ping from a machine that is on the inside out to the outside and it should return “Destination port unreachable”</p>]]></content><author><name>Brian McCammon</name></author><summary type="html"><![CDATA[I have been wanting to setup Snort on a CentOS based firewall for a while and I finally got around to it. The good thing is I finally got it working thanks to a blog Dennis Panagiotopoulos here, I have confirmed this works for CentOS 6.6 and 7.1. The problem is as with getting Snort to run inline. I was unable to find any thing on getting this to work correctly. So here is what I had to do in addition to Dennis’s blog post:]]></summary></entry></feed>