Oreoluwa Adesina

Oreoluwa Adesina

Sharing my thoughts and experiences.

Dual Protocol Learnings

Posted on October 5, 2023

In my short storage experience, managing Windows computers and file shares, especially SMB shares, has been a challenge due to their complex configuration compared to NFS shares. Recently, I explored dual protocol volumes, combining NFS and SMB, which brought its own set of challenges.

This write-up aims to share my one-month learning journey for others’ benefit. The main goal is to guide the mounting of dual protocol volumes (NTFS and UNIX security styles) on Windows and Linux clients, along with user mapping and permissions setup.

Steps

  • Create Compute Instances
  • Create the Domain Controller
  • Join Windows instance to Active Directory (AD)
  • Create User for joined instance
  • Create the Active Directory Policy
  • Create the Volumes
  • Set firewall rules
  • Mount the volumes to the Linux and Windows clients
  • Test Permissions

    • Unix Security Style

      • Mount NFS to the SMB share and try to edit the contents/ add new content; should not work for user
      • Give permissions on the mounted share 
      • Map User Identifier (UID) and Group Identiifier (GID) to windows client
      • Remount the NFS drive on windows and try first step again
    • NTFS Security style

      • Mount SMB share to NFS client and try to read/write, should not work
      • Go to windows and then name map the Security Identifier(SID) to the UID/GID
      • Remount the drive and perform first tasks again

I am a visual person so I put together an architecture to visually describe my testing Pasted image 20231002121134

In this configuration, we have three Compute Engine instances and a Google Cloud NetApp Volumes(GCNV)/Netapp Cloud Volumes Service(CVS) dual protocol volume. The AD (Active Directory) server will serve as the domain controller for the Windows Server Client. Both the Windows server Client and the Linux VM will be associated with individual users. Notably, the AD server will also be integrated with the NetApp Volumes/CVS volume.

Now, let’s dive into the exciting part where we put all these elements into action.

Create Compute instances

- Linux VM
- Windows VM
- Windows VMx2 (AD Server)

I firmly believe in leveraging infrastructure as code whenever feasible, and in this case, I’ll be utilizing Terraform for deploying these instances. I’ll be sharing the code on my GitHub page, enabling those interested to follow along and replicate the deployment process.

1 Linux VM deployment

# Required_Providers
provider "google" {
  credentials = file("gcpkey.json") # gcp servive account key
  project     = var.gcp_project
  region      = var.region  
}
#DEPLOY_UNIX_INSTANCE
resource "google_compute_instance" "linux_instance" {
  name         = var.unixinstance # vm name in my case 'debian vm'
  machine_type = "n1-standard-2"  # Change to your desired machine type
  zone         = "us-east4-a"  # Change to your desired zone

  boot_disk { 
    initialize_params {
      image = "projects/debian-cloud/global/images/debian-11-bullseye-v20230912" 
    }
  }

  network_interface {
    network = var.network # vpc name

  }

  tags = ["linux", "dualprotocol"]

}

2 Windows VM deployment

# DEPLOY WINDOWS INSTANCE
resource "google_compute_instance" "windows_instance" {
  name         = "windows-instance"
  machine_type = "n1-standard-2"  # Change to your desired machine type
  zone         = "us-east4-a"  # Change to your desired zone

  boot_disk {
    initialize_params {
      image = "projects/windows-cloud/global/images/windows-server-2019-dc-v20220615"
    }
  }

  network_interface {
    network = "default"
    
  }

  tags = ["windows", "dualprotocol"]

  lifecycle {
    ignore_changes = all
  }
}

3 Windows VM (AD server deployment) For this specific deployment, I’ve opted for an image available on the marketplace that utilizes Google’s Deployment Manager for VM provisioning. I find this approach more convenient for my purposes compared to using Terraform. Active Directory Domain Controller 2022 Pasted image 20231002125917

Once this is all done, you should see your google compute engine page look something like this: Pasted image 20231002130926

Create Domain Controller

In this step, we’ll establish an RDP connection to the Active Directory VM and initiate the Windows Server upgrade to a domain controller. Here’s a breakdown of the necessary actions:

1 Set a password for RDP session 2 RDP with credentials Pasted image 20231002132419

3 Promote the server to Domain Controller
a) First you want to reserve a static IP for the windows server, and set the DNS for the DC
b) Then you can go through a wizard that will walk you through the steps of configuring the DC
c) Restart the RDP session once complete and login with admin credentials.
Ive added a short video walkthrough of this process.

Join Windows Server to the Domain

In this phase, we’ll join the standalone “windows-instance” into our AD domain, following these sequential steps:
a Begin by setting a password for the VM and initiating a Remote Desktop (RDP) session.
b Next, configure the Windows VM’s DNS settings to point to the static IP address of the previously established domain controller.
c After configuring DNS, perform a ping test to verify connectivity between the VM and the domain controller.
d Subsequently, change the workgroup to the domain.
e Following this adjustment, the VM will automatically restart.
f To ensure the changes are successfully applied, log into the Windows VM using the domain admin credentials.
Ive added a short video walkthrough of this process.

Create User for joined instance

In this section, we’ll create a distinct user, separate from the root user, to conduct tests on read and write permissions and name mapping across both Windows and Linux clients. Here’s how to proceed:
a Commence an RDP session on the AD server.
b Log in using the AD admin credentials.
c Add a new user to the system.
Ive added a short video walkthrough of this process.

Sign into domain-joined windows server with new user

For the purpose of user separation, let’s proceed with signing into the server using the newly created user. Follow these steps:
a Initiate an RDP session on the Windows instance.
b Log in using the credentials of the recently created user.
Please note that you may need to grant permissions to allow domain users to RDP into the Windows VM to complete this step successfully.

Creating the Active Directory Policy

An Active Directory policy tells NetApp Volumes how to connect to Active Directory. Storage pool configurations use Active Directory policies to define the Active Directory settings of volumes created within them. Active Directory policies are region-specific, with the ability to configure only one policy per region. I will be implementing Infrastructure as Code (IaC) for this deployment, and you can access the code in the GitHub repository linked for reference.

# ADD ACTIVE DIRECTORY POLICY TO NETAPP CVS
# local variables
locals {
  region = "your gcp region"
  connection_type = "hardware or software"
  ad_username = "admin username"
  ad_password = "your_ad_password"
  ad_domain = "your domain"
  ad_dns_server = "dns IP"
  ad_net_bios = "netbios name"
  
}


resource "netapp-gcp_active_directory" "gcp-active-directory" {
  provider = netapp-gcp
  region = local.region
  domain = local.ad_domain
  dns_server = local.ad_dns_server
  organizational_unit = "your OU's"
  net_bios = local.ad_net_bios
  aes_encryption = true
  username = local.ad_username
  password = local.ad_password
  connection_type = local.connection_type
}


data "netapp-gcp_active_directory" "myad" {
    region = local.region
}

Once complete, your AD Dashboard should look like this (details redacted for security):
NB: The green checkmark does not guarantee connection to the AD, it just verified that there is information in all the fields for the AD policy creation. The AD connection is not verified until volume creation. Pasted image 20231002183512

Create the Cloud Volumes

Here we need to create the volumes that are going to be mounted to these clients. Again, I am going to use IaC for this as well. But before creating the volumes, we need to make sure that our VPC is peered into the CVS/GCNV Producer Project VPC as well. NetApp’s Documentation goes through why this peering is needed in much more detail and provides the instructions for the peering.

Firewall Rules

Additionally, to enable our volumes to establish communication with the Active Directory (AD), we need to create a firewall rule that permits connections from the CVS CIDR range. To achieve this, navigate to the peering tab within the VPC, retrieve the IP range, and subsequently configure a firewall rule to allow the required communication ports.

Pasted image 20231002184949 PS: I have all ports open in the screenshot above; don’t be like me, only open ports that are needed :)

Ports Needed

Pasted image 20231002185047

Once this is done, we can carry on with deploying the volumes. We are going to deploy 2 volumes 1 CVS Dual Protocol Volume with NTFS security style (Permissions are managed from the Windows side)
2 CVS Dual Protocol Volume with UNIX security style (Permissions are managed from the Unix Side)

There are different cases where each security style is useful and the documentation covers this really well

CVS Volume with NTFS Security Style

# CREATE DUAL PROTOCOL VOLUME

resource "netapp-gcp_volume" "gcp-volume" {
  name = var.volume_name_ntfs
  region = local.region
  protocol_types = var.protocol
  network = var.network
  size = var.size
  service_level = var.service_level
  storage_class = var.storage_class
  security_style = "ntfs"
  

  # Advice: Since SMB volumes can only be created if an Active Directory connection exists for the region, depend the SMB volume on the AD resource. Either create the AD from TF, or use AD data source to query for the existing AD connection
  
  depends_on = [
    data.netapp-gcp_active_directory.myad
  ]


  snapshot_policy {
    enabled = true
    hourly_schedule {
      snapshots_to_keep = 48
      minute = 1
    }
    daily_schedule {
      snapshots_to_keep = 14
      hour = 23
      minute = 2
    }
    weekly_schedule {
      snapshots_to_keep = 4
      hour = 1
      minute = 3
      day = "Monday"
    }
    monthly_schedule {
      snapshots_to_keep = 6
      hour = 2
      minute = 4
      days_of_month = 6
    }    
  }

  export_policy {
    rule {
      allowed_clients = "0.0.0.0/0"
      access= "ReadWrite"
      nfsv3 {
        checked =  true
      }
      nfsv4 {
        checked = false
      }
    }
  }
}

CVS Volume with UNIX Security Style

# CREATE DUAL PROTOCOL VOLUME

resource "netapp-gcp_volume" "gcp-volume2" {
  name = var.volume_name_ntfs
  region = local.region
  protocol_types = var.protocol
  network = var.network
  size = var.size
  service_level = var.service_level
  storage_class = var.storage_class
  security_style = "unix"
  

  # Advice: Since SMB volumes can only be created if an Active Directory connection exists for the region, depend the SMB volume on the AD resource. Either create the AD from TF, or use AD data source to query for the existing AD connection
  
  depends_on = [
    data.netapp-gcp_active_directory.myad
  ]


  snapshot_policy {
    enabled = true
    hourly_schedule {
      snapshots_to_keep = 48
      minute = 1
    }
    daily_schedule {
      snapshots_to_keep = 14
      hour = 23
      minute = 2
    }
    weekly_schedule {
      snapshots_to_keep = 4
      hour = 1
      minute = 3
      day = "Monday"
    }
    monthly_schedule {
      snapshots_to_keep = 6
      hour = 2
      minute = 4
      days_of_month = 6
    }    
  }

  export_policy {
    rule {
      allowed_clients = "0.0.0.0/0"
      access= "ReadWrite"
      nfsv3 {
        checked =  true
      }
      nfsv4 {
        checked = false
      }
    }
  }
}

Once that is done, you should have 2 volumes in your CVS Volumes Dashboard: Pasted image 20231002185427

Mounting the Volumes

Now that the volumes are set up, we can go ahead and mount the Dual Protocol volumes to the clients we created earlier:

  1. Mounting the Dual Protocol volume to NFS Follow the instructions in the CVS Mount instructions window for your particular linux distro

    Im using a Debian distro, so after following the instructions and mounting, I listed the directories to make sure my dual-protocol volumes (both unix and ntfs security styles) have been mounted to the directories I created. Pasted image 20231003110935

  2. Mounting the Dual Protocol volume to Windows Follow the instructions in the CVS Mount instructions window for your windows client Pasted image 20231003104903

    Once done, your windows client should also have both volumes with different security styles mounted on your windows clients Pasted image 20231003105340

Here, “elated-mystifying-gimmi” is the unix security style volume “xenodochial-keen-prashant” is the ntfs security style volume

Testing Permissions

Testing initial permissions on both volumes with different security styles

Now lets test permissions for the volumes, especially the ntfs security style volume, let me mount this volume from my linux client and try to write a test file on that volume: As expected, we encounter a permission denial. This occurs because the CVS volume seeks my Linux user within the Active Directory (AD) but cannot locate it. The NTFS security style volume is unable to resolve the UID and GID of the user since it is looking for a SID instead. This is where the concept of name mapping becomes crucial.

Name Mapping

Depending on the protocol used by the client (NFS or SMB) and the security style of the volume (UNIX or NTFS), NetApp Volumes can directly check access permissions of the user or requires mapping the user to the other platform’s identity first. The table below goes through different scenarios where name mapping is needed

Access protocol Security style Identity used by protocol Required mapping
NFSv3 UNIX User ID and group ID N/A
NFSv3 NTFS User ID and group ID User ID to username to security identifier
SMB UNIX Security identifier Security identifier to username to user ID
SMB NTFS Security Identifier N/A

From this table, we see that we will be able to mount and manage NFSv3 volumes with unix security style without mapping and SMB volumes with ntfs security style without name mapping as well. Now consider these 2 scenarios:

1 Scientist Charlie E. (charliee) wants to access a CVS/Google Cloud NetApp volume using SMB from a Windows client. Because the volume contains machine generated results provided by a Linux compute cluster, the volume is configured to store UNIX permissions. or 2 Engineer Amal L. needs to access some data on a volume from a Linux client using NFS. Because the volume is mainly used to store Windows data, it is configured with the NTFS security style. PS: These examples are taken from the excellent documentation available on the NetApp CVS/GCNV documentation page.

PS: When you create a dual-protocol SMB and NFS volume, Netapp strongly recommends that Active Directory contains a default user. The default user is used when an NFS client sends an NFS call with a user ID that isn’t available in Active Directory. NetApp Volumes then tries to look up a user called pcuser, which acts as a default UNIX user. If that user isn’t found, access is denied to the NFS call.

Netapp recommends that you create a default user in Active Directory with the following attributes:

  • uid = pcuser
  • uidnumber = 65534
  • cn = pcuser
  • gidNumber = 65534
  • objectClass = user

Once the default user is created, I am going to map my linux instance user (oreoluwaadesina) to the AD user I created earlier (oadesina) and the simple way of doing this is: 1 Get your uid and gid from your linux instance Pasted image 20231003120531 2 Start an RDP session into the domain controller with the AD administrator credentials 3 Modify the user attributes and add the following

  • uid = username #mine was oadesina
  • uidnumber = linux uid number #mine was 1000
  • cncomputer name #mine was oreoluwa adesina
  • gidNumber = linux gid number #mine was 1001
  • objectClass = user

4 Save the settings. Mine looked like this after mapping:

Permission Testing Continued…

Now that we have mapped the linux UID to the windows SID, let us assign permissions on the volume for our windows user

Now lets test those permissions on the windows server Lets also test this on the linux instance as well just to make sure our name mapping worked

So now we are able to read the files on the volume but are not able to write to the volume in accordance with the permissions specified on the share, pretty nice!

Lets also test permissions on the Unix security style volume after the name mapping. Initially my windows user could not access the NFS share as well, but after mapping my linux user to my windows user, and setting the permissions for my user from my linux instance Pasted image 20231004090753 I added read write permissions from my user, and then tested from the windows server with the name mapped user, and the permissions were reflected over there as well.

This write-up only covers NFSv3 name-mapping, I will post an updated version of my learnings once I’m able to learn about NFSv4 as well. Thanks for reading.