How to Managed Distributed File System (DFS) Links with PowerShell

Distributed File System (DFS) Links reduce the complexity of working with network file shares. DFS Links allow users and applications to access a “virtual path name” to connect to shared folders. We can create DFS links with PowerShell.

This “virtual namespace” enables administrators to present shared folders located on different servers, or even change a shared folder’s location, completely transparent to that folder’s consumers.

Users will not need to update bookmarks, and applications will not be required to be updated with new paths when File Servers change.

Benefit to Users

For the users, access to network share folders is simplified down to a “namespace\FolderName” format, a reduction in the complexity associated with folders stored on remote servers.

Benefit to Applications

For applications, hard-coded paths to resources on the network do not have to be changed due to a change in the network path. A simple update to the DFS Link and the application will continue to access the resources at their new location.

Prerequisites for the DFS Server Role

  • Active Directory
  • File and Storage Services role installed on a Windows Server:
  • Windows Server (Semi-Annual Channel)
  • Windows Server 2016
  • Windows Server 2012 R2
  • Windows Server 2012
  • Windows Server 2008 R2 Datacenter/Enterprise

Prerequisites for PowerShell cmdlets:

  • An administrator account with the proper permissions
  • RSAT Tools with the ‘File Services Tools – DFS Management Tools’ installed

Enabling DFS Tools with PowerShell

Download and install RSAT
Next, you need to Enable the Distributed File System Tools
* Open PowerShell as an Administrator
* Run the Install-WindowsFeature command:

How to Set Up DFS with PowerShell

We first need to install all of the necessary Windows features. This will install DFS Management GUI, the DFS Namespaces module for Windows PowerShell to create DFS links with PowerShell and manage them, and command-line tools, but it does not install any DFS services on the server.

Administration of DFS Links

You can administer namespaces by using DFS Management GUI, the DFS Namespace (DFSN) Cmdlets in Windows PowerShell, the DfsUtil commands, or scripts that call WMI.

Common PowerShell commands

Get-DfsnRoot – Discover all DFS Namespaces in the current domain
– Commonly used to check for available namespaces in the current domain

New-DfsnFolder – Create a new DFS Folder Name
– Commonly used to create a new DFS Folder in a NameSpace

New-DfsnFolderTarget – Assign path(s) to a DFS Folder Name
– Commonly used to assign one or more network folder paths to a DFS Folder

Remove-DfsnFolderTarget – Removes a path from a DFS Folder but does not remove the DFS Folder.
– Commonly used to remove one or more network folder paths from a DFS Folder

Remove-DfsnFolder – Removes a folder and all its paths
– Commonly used to remove a DFS Folder from a NameSpace

Finding DFS namespaces with PowerShell

We’ll start out by getting an idea of all the online and available NameSpaces in the current Domain using the cmdlet Get-DfsnRoot.

This shows that there are two NameSpaces that are Online in this domain.

Finding DFS folders with PowerShell

Using the Get-DfsnFolder command we can list the DFS Folders in each NameSpace.

From this output, we can see that in the AppRoot NameSpace this is not a DFS Folder named PowerShell.

Creating DFS Link Folders with PowerShell

In this example, we have a replicated folder named PowerShell on our 3 File Services servers
* FileServer01
* FileServer02
* Datacenter

The goal is to share this replicated folder with our Admins using a single path.

To do this, we’ll create a new DFS Link folder in the AppRoot NameSpace called PowerShell using New-DfsnFolder and point it to the Datacenter server’s FileShare, set the DFS Folder State to Online and set the TargetPath state to Online.

In the DFS Management GUI, we can see that the “PowerShell” DFS Folder does not exist.

Our Folder Target UNC Path

Run PowerShell and check for the DFS FolderTargetPath

\\Tech.io\AppRoot\PowerShell – if it doesnt exist it will write the output ‘Path not found. Clear to proceed’ in green text in the terminal window.

From the output we see that:
* Path has been created
* Referral Priority Class is set to Global-High
* State is Online

The GUI confirms what PowerShell told us.

and our path is now available in Windows Explorer

Creating DFS Folder Targets with PowerShell

Now that we successfully created the “Powershell” DFS Folder in our NameSpace, we’re going to add an additional Folder Target Path to it and set that path as Online using New-DfsnFolderTarget.

Up to this point, we have two of our three Server Paths added, and online. For our last Folder Path, we want to add the path but not make it available to users. So let’s add a Folder Target Path to our “PowerShell” DFS Folder and this time set the DFS Folder Path State to Offline we will again use New-DfsnFolderTarget

FileServer01 and Datacenter’s path is currently Online
FileServer02‘s state has been set to Offline

Setting DFS Folders Targets to Offline or Online with PowerShell

We can change which servers are the Online and Offline hosts, and even which will be our server will be the primary host of the file path using Set-DfsnFolderTarget.

As you can see below in the ScreenCap FileServer01‘s path has changed to Offline
Datacenter server’s ReferralPriorityClass has switched to sitecost-normal from global-high
Also, notice that FileServer02‘s path has changed its state to Online and its ReferralPriorityClass has switched to global-high

Removing DFS folder target paths with PowerShell

I try to vaccinate my code against the Fat Finger Flu as much as possible. Here we will try to install a “Safety Net” before removing one of the FolderTargetPaths by making sure that it is at least Offline before deleting it.

So long path FileServer01

For those who prefer to “cowboy” it up and forego the “safety net” option, we can accommodate you, brave souls, also.

We’ve bid adieu to the path to FileServer02

Removing DFS Folders with PowerShell

It’s has been a long and winding path, but the time for our DFS Link has come to an end. We can Remove the PowerShell folder, DFS Link, using Remove-DfsnFolder.

A quick double-check of the DFS Management GUI shows our DFS Link is no more.

One final note…These commands are only removing the DFS Links, no folders were harmed in the production of this demo.

For More Information about DFS Links

How to manage Distributed File System links with PowerShell

How to manage Distributed File System links with the GUI

Other Helpful TechSnips

Josh King’s Snip on Splatting at TechSnips.io

Matt McElreath’s Snip on Using Visual Studio Code to do Splatting at TechSnips.io

Microsoft – DFS Overview

How to “Rename” Amazon S3 “Folder” Objects with Python

 

To rename a folder on a traditional file system is a piece of cake but what if that file system wasn’t really a file system at all? In that case, it gets a little trickier! Amazon’s S3 service consists of objects with key values. There are no folders or files to speak of but we still need to perform typical filesystem-like actions like renaming folders.

Renaming S3 “folders” isn’t possible; not even in the S3 management console but we can perform a workaround. We can create a new “folder” in S3 and then move all of the files from that “folder” to the new “folder”. Once all of the files are moved, we can then remove the source “folder”.

To do this, I’ll be using Python and the boto3 module. If you’re working with S3 and Python and not using the boto3 module, you’re missing out. It makes things much easier to work with.

Prerequisites

For the demonstration I’ll be showing you to work, you’ll need to meet a few prereqs ahead of time:

  • MacOS/Linux
  • Python 3+
  • The boto3 module (pip install boto3 to get it)
  • An Amazon S3 Bucket
  • An AWS IAM user access key and secret access key with access to S3
  • An existing “folder” with “files” inside in your S3 bucket

Renaming an Amazon S3 Key

To rename our S3 folder, we’ll need to import the boto3 module and I’ve chosen to assign some of the values I’ll be working with as variables.

Once I’ve done that, I’ll need to authenticate to S3 by providing my access key ID and secret key for the IAM user I’ll be using. In this case, I’ve chosen to use a boto3 session. I’ll be using a boto3 resource to work with S3.

Once I’ve done that, I then need to find all of the files matching my key prefix. You can see below that I’m using a Python for loop to read all of the objects in my S3 bucket. I’m using the optional filter action and filtering all of the S3 objects in the bucket down to only the key prefix for the folder I want to rename.

Once I’ve started the for loop iterating over the “folder” key and all of the “file” keys inside of it, I’ll then need to exclude the “folder” key itself since I won’t be copying that. I just need the file keys. I’m excluding that by an if statement that matches all key values that don’t end with a forward slash.

After I’m in the block that will only contain file key values, I’m now assigning the file name and destination key names to make it easier to reference.

Once I have all of that setup, I then finally do the actual copy using the copy_from action. You can see below that I’m creating an S3 object using the bucket name and destination file key. I’m then passing the source key to the copy_from action.

Once the loop has finished and all of the files have been copied to the new key, I’ll then need to use the delete action to clean all of the files including the “folder” key since it is not inside of the if condition.

At this point, we’re done! You should now see all of the files that were previously in the source key under the destination key with no sign of the source key!

How to Write to a Text File with PowerShell

A common need amongst IT professionals is to create and append to text files. The ubiquitous nature of a plain-text file lends itself to lots of uses. In a PowerShell script, we can quickly create and append to plain-text files using a couple of built-in cmdlets called Add-Content and Set-Content. In this article, let’s go over how we can use both of these cmdlets to handle all of our text file needs.

Both the Add-Content and Set-Content cmdlet both perform similar functions; creating and writing to text files but they behave a little differently. The biggest difference is one always appends text to a file while the other always overwrites it. This is important to know when you’re writing to an important log file!

Continue reading “How to Write to a Text File with PowerShell”

How to Create a PSCredential Object Without Using Get-Credential in PowerShell

PSCredential objects are commonplace in PowerShell. They are a creative way to store and pass credentials to various services securely. Many built-in and third-party cmdlets require PSCredential objects on many different commands.

Typically, to create a PSCredential object, we’d use the Get-Credential cmdlet. The Get-Credential cmdlet is the most common way that PowerShell receives input to create the PSCredential object like the username and password.

Continue reading “How to Create a PSCredential Object Without Using Get-Credential in PowerShell”

How to Reference an Object Property in a String in PowerShell

Strings by themselves are a simple data type in PowerShell. Merely surrounding a set of characters with single or double quotes creates a string. But whenever you need to insert an expression inside of that string is when things get a little more complicated. This process is typically known as string interpolation.
By default, PowerShell interprets a string as a literal. For example, just typing 'This is a string' in PowerShell creates a string just fine. However, when you need to insert some expression like a variable or an object property in our case, you have to use double quotes.
String Interpolation
In this case, we used a single variable. To get an expression to expand inside of a string, we just need to insert the variable inside of double quotes but happens when we try to expand an object property?

Continue reading “How to Reference an Object Property in a String in PowerShell”

The “I’m Not Good Enough” Excuse has Officially Been Eradicated

All throughout my time in the tech communities, the common theme I keep hearing from people is “I’m not good enough” or “I could never do that!”. It’s frustrating to me because I know that every good IT guy or gal has knowledge in their head that’s people would love to learn about.

What’s stopping you?

TechSnips’ mission is to provide a platform for technology professionals to showcase their work via video screencasts. However, those that aren’t used to presenting and required more coaching than others tended to get frustrated when they were forced to re-record their screencasts due to quality concerns.

Now they don’t have to!

Continue reading “The “I’m Not Good Enough” Excuse has Officially Been Eradicated”

How to Configure OpenSSH on Windows for PowerShell Remoting Over SSH

This article is meant to bridge the gap between my video on How to Set Up OpenSSH on Windows and Ethan Bell’s How to Use PowerShell Remoting Over SSH. After installing OpenSSH on Windows, there are a few settings that need to be configured on the client as well as the remote SSH server in order to allow PowerShell Remoting over SSH.

If you try to create a new PSSession over SSH after installing OpenSSH, you may see the following error:

First, we need to make sure that the path to the ssh.exe executable is in the PATH environment variable on the computer that you will be using to connect to a remote SSH server. To do this, click on the Start button and search for advanced system settings then click on View Advanced System Settings.

Continue reading “How to Configure OpenSSH on Windows for PowerShell Remoting Over SSH”

How I Learned Pester by Building a Domain Controller Infrastructure Test

“What is simple, is understood. What is understood, is executed.” -Anonymous

Let me start by saying that Pester for the longest time was very intimidating to me early in my PowerShell journey. I’m still wondering what exactly it was that made me think that way. Was it being too busy just trying to learn what I needed for that moment, or was it that I didn’t see how I could implement it into my suite of scripts? I don’t have any good answers.

The Scenario

I’m a Sysadmin by trade and recently had experienced some system issues after performing some typical routine maintenance. Some of this work I had scripted by referencing the original checklists provided to me when I first started doing this work. This particular cycle, the checklist wasn’t enough.

Continue reading “How I Learned Pester by Building a Domain Controller Infrastructure Test”

How to Run PowerShell Code by Invoking a Webhook in Azure Automation

Back in my day, we could only run PowerShell scripts on local Windows computers. Nowadays though. it’s amazing all of the different ways to execute PowerShell scripts. We not only have PowerShell on Linux but Azure Cloud Shell too! Azure Cloud Shell is an awesome way to quickly bring up a PowerShell environment to execute code in the cloud. Speaking of Azure, we’ve also got Azure Automation runbooks. Using PowerShell Azure Automation runbooks are another great way to get stuff done with PowerShell.

Whenever I build a PowerShell Azure Automation runbook, the trigger for the runbook has always been on a schedule or invoked via another runbook. However recently, I needed the ability to invoke it outside of Azure completely via a service we use here at TechSnips called Zapier.

Continue reading “How to Run PowerShell Code by Invoking a Webhook in Azure Automation”

Creating Starter Group Policy Objects for Quick Policy Baselines

If you are lucky to build a complete Active Directory infrastructure from scratch, then you know how much planning and consideration goes into the whole process. And it doesn’t just stop with delivering the environment. You have to also consider ongoing management of the environment.

That’s why you should consider using Starter Group Policy objects.

Starter Group Policy object is just a blank, or clean slate if you will, Group Policy Object. The purpose of these objects is to allow an administrator to create and have a pre-configured group of settings that represent a baseline for any future policy that is to be created. These settings can then be copied into a more formal Group Policy Object that is then applied to single or multiple organizational units (OU’s for short). Copying these starter objects preserves your baseline strategy and allows you to dynamically add or remove settings that shouldn’t be applied to future objects.

Continue reading “Creating Starter Group Policy Objects for Quick Policy Baselines”