Tuesday, July 14, 2020

TiddlyWiki + GitHub + Cloudflare

My Existential Crisis, “Storing Knowledge is hard”

I should mention that although this is generally true what I really mean by “storing knowledge is hard” is that storing Knowledge is hard for me. It’s funny to think that in some ways the scribblings of a two-year-old have a better chance of weathering our world than the bits of information needed to keep the modern enterprise afloat. Computer systems were designed to make the impossible possible, in most cases this does not mean preserving data past one lifetime, admittedly many enterprise systems will fail at that. When confronted as to why the scribblings of a youngling have better data durability than our enterprise grade systems the answer is wonderfully simple, someone cared for them. Someone put the drawings in a box, in the closet, where it would be undisturbed and knew it would be re-discovered years later by them, or by their grandchildren. The scribblings of a toddler are self-contained they do not need a program to be interpreted or relayed only the eyes, brain and heart of a human. Care it would seem is synonymous with data durability. From toddlers’ scribblings, oral traditions, hieroglyphs, Runes and words set in stone it would seem the amount we care is often deterministic and proportional to how long something exists on the face of our planet. As a Sysadmin it truly is hard to look out and see anyone building systems with that level of care, don’t get me wrong, there are passionate site reliability engineers out there, but when it comes to distributed systems what shapes the design of care is company culture and that’s both hard to measure now and difficult to predict long term. Humans are inconsistent creatures at best and at worst care far too little about each other and what is important to our fellow man.

Evernote, OneNote, Simplenote, Apple Notes, Text Files, Collected Notes, google keep, Outlook Notes, Super Notes, Zettelkasten (the archive), Roam Research, Obsidian, Standard Notes and many others… I have tried enough of them and after copious amounts of experimentation I have finally discovered what I need as a sysadmin.

The things I want as a Sysadmin:

  1. Plain text Search, I need fast, full note, plain text search.

  2. Different reading and editing modes just like vi, I want to be able to reference, copy and send what’s in my knowledge base and know that when I’m highlighting text to copy I’m not going to accidentally add, subtract, delete or move anything I’ve written unless I unlock the note first. This is important since a good chunk of what I might be copying I also might paste into another systems terminal.

  3. Markdown Support, I like markdown, it makes my life objectively better, and honestly that is no small feat on its own, I love code blocks, so much.

  4. Cross platform reading, writing, editing, I want to be able to use it on my mac, my iPhone, and my ThinkPad regardless of what OS my ThinkPad might be running.

  5. Far, it needs to work in the future not just now, more importantly my data is mine and I want to be responsible for it long term.

So, after a lot of flipping between Evernote, OneNote, etc… I discovered TiddlyWiki I spent some time and built what I needed. The next step was delivery and I struggled for far too long trying to figure out how to sync the thing between my computers, I tried OneDrive, Dropbox, Google Drive, iCloud, Syncthing (which impressed me), then I gave up and put it in Dropbox for no other reason than it was convenient and I was able to use https://twcloud.github.io/for wiki access which worked ok. But then I found something I felt was better, that is where the title of this blog comes into play:

TiddlyWiki + GitHub + Cloudflare, let me explain.

TiddlyWiki is unique, it’s an HTML Quine with a Java backbone, the output of TiddlyWiki is itself plus what you added to it. It is a self-replicating, self-contained program where saving is exporting a new TiddlyWiki source code and all, if you use it in an editor like TiddlyDesktop then your work is saved over your previous file. Someone quite cleverly figured out how to write a GitHub saver where when you hit save TiddlyWiki saves itself out to a GitHub repo.

GitHub has a wonderful feature called GitHub pages, a GitHub page gives a user the ability to expose an HTML file in their Git repo to the world, this is great! (and I bet you can see where I’m going with it already) TiddlyWiki has a built in GitHub API saver where you can save your wiki back to Github using an access token (PAT). This means you can have a TiddlyWiki that writes its output over itself directly to your GitHub repo and with a little tweaking you can store your PAT in the TiddlyWiki file itself… Except for how do you protect it? If anyone load your TiddlyWiki file, which is also the client and holds the PAT key for your GitHub someone could steal your PAT Key and do anything you can in your GitHub! Truly this is an awful Idea, so how do you keep this from happening? 1. Use a dummy GitHub account as a collaborator and give the dummy access to only your TiddlyWiki repo using the dummy’s pat key in your TiddlyWiki file. This way if your TiddlyWiki file is ever compromised the most someone can do with the PAT is access the dummy account and its data. 2. I am using this for my technical notes, they do not contain passwords, keys, or information I would hesitate to share with my peers. Be smart and store sensitive information in an encrypted password vault/manager where it belongs not on a potentially public website.

Let’s make it secure, enter Cloudflare Access and custom domains for github.io, Cloudflare Access is awesome it allows you to take a custom domain or subdomain and prevent access to it unless a user can verify themselves with a one time code sent via email. With Cloudflare Access in front of your Wiki the security model changes to a verification model, in theory as long as there’s no alternate way to load your HTML file outside of your domain the access control remains. GitHub fortunately allows custom domains, when you add a custom domain to your GitHub.iopage GitHub will redirect any request to your GitHub page to your domain and thus to Cloudflare access as the gate keeper.

Disclaimer, as far as I know there’s no way around the GitHub pages redirect, if there is a way to query GitHub pages for an HTML page without going through the custom domain this whole setup is borked and will never be secure, do your research, be smart, make good choices.

Setup, Let’s Build It!

  1. Some prerequisites own a domain, choose a subdomain and make Cloudflare your DNS host (Cloudflare Access is $3 per month). You will also need a GitHub Pro account.
NOTE: In Cloudflare you should make the following changes,
	1. Set your SSL/TLS Encryption mode to Full Strict
	2. Under Edge Certificates allow only TLS 1.3 Connections
	3. Consider creating firewall rules that disallow endpoints from connecting to your wiki subdomain from outside of your current country.
  1. In GitHub build a private repo for your Wiki.

  2. Create another GitHub free account which will be the writer to your wiki enable 2fa for both accounts and generate a PAT in the free account save this for step 8.

  3. Create the subdomain you want your wiki to be hosted at in Cloudflare creating the following A records that point to the following IP addresses:

Warning DO NOT USE CNAME RECORDS HERE GITHUB WILL PROMPT YOU TO BUT DO NOT DO IT, doing so will bypass Cloudflare access, it may also be a good idea not to use Cloudflare Proxied records for these records doing so caches content and you want to make sure your TiddlyWiki is loaded fresh each time you load it.
  1. Enable Cloudflare access and allow either your email address or a set of addresses in your domain to login to the subdomain.
  2. Enable GitHub pages and add your subdomain.
  3. Wait for DNS to propagate and go to your new subdomain you should be brought to the Cloudflare Access page.

Before step 8 I should point out that if you have not configured Cloudflare correctly you may compromise your dummy GitHub Account. You should never store secrets in a GitHub repo, its ill-advised and without taking steps to secure the gate with Cloudflare you will end up with someone else holding one of your Personal Access Tokens. YOU HAVE BEEN WARNED.

8. Danger Will Robinson! Danger! STEP 8

On line 25 in $:/core/modules/savers/github.js change the password entry to look like the following:

password = this.wiki.getTiddlerText("$:/GitHub/PAT"),
  1. Next make a Tiddler named $:/GitHub/PAT and add your Personal Access Token into this Tiddlers text and plan on bookmarking it so when you change your access token in the future you can easily change this Tiddler as well. Once done you can click the save button in TiddlyWiki which should write to your GitHub repo, with an HTML file in place you can now enable GitHub pages.

If you have done everything correctly you should find that when you go to the subdomain you set in Cloudflare that you are greeted by Cloudflare access and that once authenticated you can load your TiddlyWiki file, and write back to it.

Tuesday, June 23, 2020

Tweaks and best practices for Office 365

A list of tweaks and best practices for configuring Office 365 most of these were shamelessly stolen from the sysadmin today podcast, some were also taken from Microsoft Office 365 deployment guidance. As Microsoft continues to develop their platform much of this will change but I think at the moment this is a great starting point.
  1. Establish main tenant administrator with strong password and MFA and create a break glass global admin account using yourtenet.onmicrosoft.com so if a mistake is made you can still login to Office 365 as a global admin. 

  2. Enable/Verify that modern authentication is enabled and or enable security defaults in azure AD, if you are deploying hybrid configure conditional access rules so your Exchange service account is never prompted for 2fa from your exchange servers IP.

  3. Setup tenant profile with organization information: https://admin.microsoft.com/AdminPortal/Home#/companyprofile

  4. Configure Account Recovery Options: https://aka.ms/ssprsetup

  5. Grant Delegated Admin to CSP (if MS Partner)

  6. Disable self service Purchases across the board:

Install-Module -Name MSCommerce #once you install you should remove this line
Import-Module -Name MSCommerce 
Connect-MSCommerce #sign-in with your global or billing administrator account when prompted
Get-MSCommerceProductPolicies -PolicyId AllowSelfServicePurchase | forEach { 
Update-MSCommerceProductPolicy -PolicyId AllowSelfServicePurchase -ProductId $_.ProductID -Enabled $false  }
  1. Consider limiting group creation so that only users of the group “Group Admins” security group are allowed to create office 365 groups: https://docs.microsoft.com/en-us/office365/admin/create-groups/manage-creation-of-groups?view=o365-worldwide

  2. Configure Tenant alerts email addresses as a distribution group and set it in powershell.

Set-AzureADTenantDetail -SecurityComplianceNotificationMails "alerts@domain.com" - TechnicalNotificationMails "alerts@domain.com" -MarketingNotificationEmails "alerts@domain.com"
  1. Enable Unified Audit Logging
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $True
  1. Enable Mailbox Audit Logging
$AuditSettings = @{
AuditEnabled = $True AuditLogAgeLimit = 365 AuditOwner =
"Create,HardDelete,MailboxLogin,Move,MoveToDeletedItems,SoftDelete,Update,UpdateCale ndarDelegation,UpdateFolderPermissions,UpdateInboxRules"
AuditDelegate = "Create,FolderBind,HardDelete,Move,MoveToDeletedItems,SendAs,SendOnBehalf,SoftDelet e,Update,UpdateFolderPermissions"
AuditAdmin = "Copy,Create,FolderBind,HardDelete,Move,MoveToDeletedItems,SendAs,SendOnBehalf,Soft Delete,Update,UpdateCalendarDelegation,UpdateFolderPermissions,UpdateInboxRules"
Get-Mailbox | Set-Mailbox @AuditSettings
  1. Set Language and Time Zone for All Users this will save them a step when they first sign in
Get-Mailbox | Get-MailboxRegionalConfiguration | ? {$_.TimeZone -eq $null} | Set-MailboxRegionalConfiguration -Language 1033 -TimeZone "Central Standard Time"
  1. Increase Deleted Item Retention from 14 to 30 Days
Get-Mailbox -ResultSize unlimited | Set-Mailbox -RetainDeletedItemsFor 30
  1. Show mailtip for External Recipients
Set-OrganizationConfig -MailTipsExternalRecipientsTipsEnabled $True
  1. Show mailtip for large number of recipients (Shows tip Beyond threshold)
Set-OrganizationConfig -MailTipsLargeAudienceThreshold 10
  1. Set Outbound Spam Notifications
Set-HostedOutboundSpamFilterPolicy Default -NotifyOutboundSpam $true - NotifyOutboundSpamRecipients “alerts@domain.com”
  1. Prevent Inbox Rules Forwarding Messages Externally, strongly recommend. 
Set-RemoteDomain Default -AutoForwardEnabled $false
  1. Prepend Disclaimer on External Messages
$TransportSettings = @{
Name = 'External Sender Warning'
FromScope = 'NotInOrganization'
SentToScope = 'InOrganization'
ApplyHtmlDisclaimerLocation = 'Prepend' ApplyHtmlDisclaimerText = "<p><div style='border:solid #9C6500
1.0pt;padding:2.0pt 2.0pt 2.0pt 2.0pt'><p class=MsoNormal style='line- height:12.0pt;background:#FFEB9C'><b><span style='font- size:10.0pt;color:#9C6500'></span></b><span style='font- size:10.0pt;color:black'>[EXTERNAL]<o:p></o:p></span></p>"
ApplyHtmlDisclaimerFallbackAction = 'Wrap' }
New-TransportRule @TransportSettings
  1. Increase OneDrive Deleted User Retention (up to 3650 days) no typo 10 years is correct and can be configured.
Set-SPOTenant -OrphanedPersonalSitesRetentionPeriod 180
  1. Disable IMAP / POP Protocols For Current Users, also strongly recommend.
Get-CASMailbox -Filter {ImapEnabled -eq "true" -or PopEnabled -eq "true" } | Select-Object @{n = "Identity"; e = {$_.primarysmtpaddress}} | Set-CASMailbox -ImapEnabled $false -PopEnabled $false

and for Future Users

Get-CASMailboxPlan -Filter {ImapEnabled -eq "true" -or PopEnabled -eq "true" } | set-CASMailboxPlan -ImapEnabled $false -PopEnabled $false
  1. If migrating a large environment call Microsoft and ask them to disable throttling for your tenet.


Azure AD Notes (Some features may require advanced licensing like Azure AD Premium P1)

Reporting Audits

Saturday, June 13, 2020

Useful Group Policy WMI Filters

One of group policy’s best yet seldom used features is WMI filtering which allows an admin to apply policies to windows computers conditionally instead of statically based on what OU a computer or user object is in. Here are a few of my favorites, all of them are in root\CIMv2 unless otherwise specified.

Filter by OS Install Date Incredibly useful if you are looking to push new software automatically to only new computer or computers that have been freshly imaged with MDT. The example below will only apply to computers that have an install date greater than 2016-04-09

SELECT * FROM win32_operatingsystem WHERE Installdate>="20160409111400.0+0"

Filter by Memory Type This allows you to filter by desktops and laptops if you have desktops that do not have sodimm memory. If you do have desktops with sodimm memory you might combine this with another WMI filter that queries if systems have a battery present

Note that If you have systems which are small form factor and have UPS’s attached this may not work for you.

Desktops (devices not using SODIMMs)

Select * from Win32_PhysicalMemory WHERE (FormFactor != 12)

Laptops (devices using SODIMMs)

Select * from Win32_PhysicalMemory WHERE (FormFactor = 12)

Filter by Windows Desktop Operating Systems Filtering by Windows Desktop Operating Systems is useful if you have changed the default Computers Container to an OU with policies applied, doing this ensures that when Servers are joined to the domain and appear in an OU instead of a container they do not pickup group policies designed for desktops.

select * from Win32_OperatingSystem WHERE ProductType = "1"

Filter for Windows 10

select * from Win32_OperatingSystem where Version like "10.%" and ProductType="1"

Filter for a specific build of windows 10 In this case windows 10 1909 useful if you want to control windows update with group policy.

select * from Win32_OperatingSystem where Version like "10.0.18363" and ProductType="1"

Filter for 64 Bit Windows Servers

select * from Win32_OperatingSystem where (ProductType = "2") OR (ProductType = "3") AND  OSArchitecture = "64-bit"

From these you should find that you can filter just about all the various parts of your windows 10 infrastructure.

Saturday, April 25, 2020

Changing Default Containers to OU's in AD

In windows by default there are two containers, the Computers container and Users Containers. When you join new workstations, servers or add new users to your domain they will show up in either of these by default and no policies will be applied to them until you move the user or computer object into an OU. This is because Group Policy Objects do not apply to containers only OU’s. Luckily you can change where active directory puts computers and users upon creation using the following commands:

Set the default OU for new computers to land in using redircmp

C:\Windows\system32>redircmp "OU=New Computers,OU=Computers,OU=Your OU,DC=ORG,DC=COM"
Redirection was successful.

Set the default OU for new user accounts to land in using redirusr

C:\Windows\system32>redirusr "OU=New Accounts,OU=Accounts,OU=Your OU,DC=ORG,DC=COM"
Redirection was successful.

Once done you should find that newly added users and computer land in your newly designated OU’s which will allow you to do things like automatically push software to new workstations via group policy or make sure that new users get their home folders and network drives mapped without any further changes.

Useful Links

A collection of things that I’ve found useful for one reason or another during my time troubleshooting windows workstations and helping end users. Hopefully you will find them as helpful as I have.

The links to these tools contain the MD5 as the downloads are hosted by myself from a Backblaze bucket you should check the MD5 of what you download before you run any of it, checking the MD5 does not make the software safe but it does make sure that at least you got what you attempted to download check your MD5 elsewhere to confirm. None of this software is mine this is just a collection of links to acquire it use at your own risk.

TFC MD5: 788fcddd88240a85039f7f561093b118
The temp file cleaner by old-timer is a classic utility designed to clean all the old temp files off of windows systems, works with Windows xp - Windows 10
Take Ownership MD5: 38a8674b9bb64a27ec999fcc9e3df662
An old registry hack that enables a take ownership right click option, useful for when you’re stuck with a file you can’t seem to change the permissions of even though you have admin access.
hpflash1 MD5: e30ffd26b45c78303085dc4f35a24a80
The HP flash utility, great for making DOS boot drives.
DoubleDriver MD5: 98f948a5806cf6d84bfb2dabc8c48a95
Double Driver, the unsung hero of printer migrations and new system builds. This utility can suck the drivers right out of an existing windows install and throw them directly at a new one.
Putty! For all your SSH, Serial and Telnetting needs, no direct download provided go get it from the source.
for when you really need to check and see if you can configure something with Group Policy.
Windows CLI things Get the service tag of dell PC’s from Command Prompt or PowerShell
wmic bios get serialnumber
Expire a computers kerberos ticket thus forcing the computer to get a new one this helps windows detect a change in AD OU’s without rebooting so that you can run gpupdate /force without needing to reboot. Useful for systems that cant be shut down but do need to be moved in AD.
klist -li 0x3e7 purge

Group Policy Troubleshooting from the Command Prompt

A series of useful tips and tools for diagnosing group policy issues in windows.

Force a system to expire its current kerberos ticket, this will make the system check what OU its in and thus apply any new group policy’s. Useful if you have moved a computer to a new OU and need it to apply the new policies of that OU but cant afford the down time of a reboot.

klist -li 0x3e7 purge

Change what domain controller group policy is being pulled from. This is especially useful if you have just discovered that your DFSR SYSVOL is no longer replicating correctly.

nltest /dsgetdc:example.com
nltest /Server:$ClientComputerName /SC_RESET:example.com\dc.example.com

See policies applied to the local computer

gpresult /r

Getting the group policy results from a workstation through psexec

gpresult /user User-Logged-In /scope computer /r

See remotely installed printers I use:

wmic printer list brief
wmic printer get name

This just shows a short list of printer attached to the system you run the command on. It will also show what computer a printer is connected to if there’s a network printer.

You can also use this to get a very detailed list of configuration for each printer installed on a system:

wmic printer list full

To output it to a text file, nothing fancy can be done with basicly any command that has an output.

wmic printer list brief >> c:\users\admin\documents\printerlist.txt

Friday, April 24, 2020

Implementing Software Restriction Policy on Windows

A guide for setting up Software Restrictions in Group Policy.
Under Enforcement Properties set “All software files except libraries (such as DLLs)”, “All users except local administrators” (which will allow members of the local administrators group to bypass the policy completely) and ignore certificate rules unless you are planning to whitelist software via certificates, this can be handy for allowing user to install some programs to %appdata% such as slack, and or certain video conferencing software.

Under Designated File Types remove .lnk files, leaving this option enabled can cause start menu items to stop working as well as all shortcuts to exe files which are now pervasive through the windows operating system. This is mentioned in the NSA document but they list making a rule to allow it, other sources recommend removing it from the designated file types list which seems to be the correct way to do this. Under Security Levels set the policy to Disallow, this will prevent software from running regardless of the access rights of the user.

Paths the NSA recommends restricting

%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\Debug
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\Registration
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\System32\catroot2
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\System32\com\dmp
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\System32\FxsTmp
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\System32\spool\drivers\color
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\System32\spool\PRINTERS
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\System32\spool\SERVERS
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\System32\Tasks
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\SysWOW64\com\dmp
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\SysWOW64\FxsTmp
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\SysWOW64\Tasks
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\Tasks
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\Temp
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot%\tracing

Paths the NSA recommends allowing

In the original document there is an invisible space right before “Windows” to be cautious of the below line has been corrected.
%HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir (x86)%
as well as sysvol so any logon scripts you have will still run, not adding this will break any logon scripts you have.
An alternate value for the x86 directory might be needed in certain versions of windows, it is not needed for windows 10. to add if the x86 exception listed by the NSA is causing difficulties adding the below line might resolve them. This should not be necessary in most cases.

Blocking The Windows Store and Xbox apps in Windows 10

Windows Store, blocking this will disable users from launching the windows store and thus prevent users from installing apps from it.
Xbox Apps, Windows 10 ships with a couple different xbox applications, removing these is problematic but blocking them from running is not. This will prevent users from downloading PC games or connecting to and streaming from xbox systems on the network or outside of it. (Microsoft is adding an ability to connect to a home xbox in a future xbox release.)

Whitelisting modern applications

Some windows applications such as OneDrive run from appdata, as such you may need to whitelist additional locations so that these applications can function properly, this also goes for windows store applications. In the case of OneDrive the path is
Applications installed from the windows app store (if you have chosen not to block them) will install to the directory C:\Program Files\WindowsApps whitelisting the specific directory can allow these to run, windows will allow you to use wildcards in the path names so for example
C:\Program Files\WindowsApps\spo*
Will allow any app contained within any folder under WindowsApps that begins with “spo” to run, in this example spotify as installed from the windows app store would run.

Other Considerations