Introduction
So far, we've demonstrated how to connect to Cerberus FTP Server and make SOAP API calls using PowerShell. We've also explored how PowerShell interfaces with the SOAP API via WSDL.
Now we demonstrate changing Cerberus' native users. Example-UserManipulation.ps1 creates a user, lists all Cerberus users, modifies the user's email address and password, adds a virtual directory to our user, and finally deletes the user.
We assume you've reviewed previous guides in this series and have successfully run HelloCerberus.ps1. You should already know how to run PowerShell scripts and change PS execution policy. You'll once again need the URL to Cerberus.wsdl, served by your Cerberus FTP Server.
Once again, we'll begin by running the script, then step through the script in detail.
Running Example-UserManipulation.ps1
Since our example script makes modifications to the Cerberus User store, it is best not to run it against your production Cerberus environment; we strongly recommend that you use an independent instance of Cerberus for testing.
- Download the script
- Open a PowerShell console to the downloaded location
- Run the script
PS C:\> & .\Example-UserManipulation.ps1 -EnableTls12 -DisableCertValidation
If all went well, you'll see something like this in the PowerShell console:
PS C:\> & .\Example-UserManipulation.ps1 -EnableTls12 -DisableCertValidation Windows PowerShell credential request. Provide master admin credentials for Cerberus FTP Server User: Admin Password for user Admin: ***************** Successfully created user PsSOAPTestUser Successfully retrieved list of users PsSOAPTestUser PsSOAPTestUser exists in the list of users Successfully updated email address of PsSOAPTestUser Successfully changed password for PsSOAPTestUser Successfully added NewRoot to PsSOAPTestUser Successfully deleted PsSOAPTestUser
Code Walk-Through
Let's review each section of this script.
Note that the style of this script differs from HelloCerberus.ps1. Objects are explicitly created and their storage variables are type-constrained with the bracket syntax. This results more verbose expressions like:
[CerberusFtp.User] $newUser = New-Object -TypeName CerberusFtp.User
We've found, though, that this syntax seems to work better with PowerShell's code-completion features. Hopefully this makes it easier to integrate snippets of this code into your own scripts.
Setup SOAP Connection
This is the same code used in HelloCerberus.ps1. Cerberus credentials are requested if not provided. TLS 1.2 and certificate validation are enabled or disabled according to parameters passed to the script. The Web Service Proxy object is created. The only significant difference is the addition of the $EnableTls12 and $DisableCertValidation switches:
# Collect credentials if not provided in parameters if (-not $PSBoundParameters.containsKey('CerberusCredentials')) { $CerberusCredentials = Get-Credential -Message "Provide master admin credentials for Cerberus FTP Server" } if ($EnableTls12) { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } if ($DisableCertValidation) { if (-not("dummy" -as [type])) { add-type -TypeDefinition @" using System; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; public static class Dummy { public static bool ReturnTrue(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } public static RemoteCertificateValidationCallback GetDelegate() { return new RemoteCertificateValidationCallback(Dummy.ReturnTrue); } } "@ } [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [dummy]::GetDelegate() } # Create Web Service Proxy object and CerberusFtp data-types $CerberusSvc = New-WebServiceProxy -Uri $WSDLUrl -Class CerberusFtp -Namespace CerberusFtp # Override default SOAP endpoint if provided in parameters if ($PSBoundParameters.ContainsKey('CerberusServiceUrl')){ $CerberusSvc.Url = $CerberusServiceUrl }
Create a New Test User
To create a user, invoke the AddUser operation passing a CerberusFtp.AddUserRequest object containing a CerberusFtp.User object. The User object must be populated with all of the properties you'd like for the user entry.
As always, create a request object corresponding to the operation we're about to invoke:
# Create new AddUserRequest object [CerberusFtp.AddUserRequest] $addUserRequest = New-Object -TypeName CerberusFtp.AddUserRequest
Every request needs credentials to authenticate:
# Populate request object with Cerberus Admin credentials $addUserRequest.credentials = New-Object -TypeName CerberusFtp.Credentials $addUserRequest.credentials.user = $CerberusCredentials.UserName $addUserRequest.credentials.password = $CerberusCredentials.GetNetworkCredential().Password
The last bit of information the AddUser operation requires is a user. Create an object of type CerberusFtp.User and populate relevant properties:
# Create new User object [CerberusFtp.User] $newUser = New-Object -TypeName CerberusFtp.User # Populate user object with user details $newUser.name = $newTestUserName $newUser.password = New-Object -TypeName CerberusFtp.Password $newUser.password.value = "TestPasswordChangeImmediately1234!@#$" $newUser.requirePasswordChange = $true $newUser.fname = "NewUserFrom" $newUser.sname = "PowerShell" $newUser.email = "NewTestUser@powershellExample.net" $newUser.desc = "This user was created from PowerShell using SOAP" # Test account not allowed to change its own password $newUser.isAllowPasswordChange = New-Object -TypeName CerberusFtp.UserPropertyBool
CerberusFtp.UserPropertyBool belongs to a family of types that deal with how user properties interact with the group membership. We'll cover this in more detail when demonstrating group operations. For now, just set the .value to $false and .valueSpecified properties to $true:
$newUser.isAllowPasswordChange.value = $false $newUser.isAllowPasswordChange.valueSpecified = $true
Repeat with the .isDisabled attribute to ensure no one may login to our new test account:
# Test account disabled $newUser.isDisabled = New-Object -TypeName CerberusFtp.UserPropertyBool $newUser.isDisabled.value = $true $newUser.isDisabled.valueSpecified = $true
Now that the user object is created, we copy it to the request object and invoke the AddUser operation:
# Populate request object with new user object $addUserRequest.User = $newUser # Issue the AddUser request [CerberusFtp.AddUserResponse] $addUserResponse = $CerberusSvc.AddUser($addUserRequest)
Finally, we test the result of the operation and display feedback accordingly:
# Check response for success or failure if (-not $addUserResponse.result){ Write-Error "Failed to create user: $($addUserResponse.message)" } else { Write-Host "Successfully created user $newTestUserName" }
Get a list of All Cerberus Users
Now that we've created a new user, we can request a list of users from Cerberus FTP Server and confirm that our new user exists in the list.
Once again, every operation must have a corresponding request object populated with admin credentials. Going forward, we'll skip details for concepts we've already covered.
# Create new GetUserListRequest object [CerberusFtp.GetUserListRequest] $getUserListRequest = New-Object CerberusFtp.GetUserListRequest # Populate request object with Cerberus Admin credentials $getUserListRequest.credentials = New-Object -TypeName CerberusFtp.Credentials $getUserListRequest.credentials.user = $CerberusCredentials.UserName $getUserListRequest.credentials.password = $CerberusCredentials.GetNetworkCredential().Password
The list of user names is sent in the $getUserListResponse.UserList property. In PowerShell, it appears as an array of strings. We can use the -contains operator to test the contents of the array for the name of our new user:
[CerberusFtp.GetUserListResponse] $getUserListResponse = $CerberusSvc.GetUserList($getUserListRequest) # Check response for success or failure if (-not $getUserListResponse.result){ Write-Error "Failed to retrieve user list: $($getUserListResponse.message)" } else { Write-Host "Successfully created retrieved list of users" Write-Host $getUserListResponse.UserList if ($getUserListResponse.UserList -contains $newTestUserName){ Write-Host "$newTestUsername exists in the list of users" } else { Write-Error "$newTestUsername was not found in the list of users" } }
Modify Email Address of a User
Modifying a user is a compound operation.
- Retrieve the user with getUserInformation
- Modify the local copy of the user
- Invoke AddUser to overwrite the user
# Create new GetUserInformationRequest object [CerberusFtp.GetUserInformationRequest] $getUserInformationRequest = New-Object CerberusFtp.GetUserInformationRequest # Populate request object with Cerberus Admin credentials $getUserInformationRequest.credentials = New-Object -TypeName CerberusFtp.Credentials $getUserInformationRequest.credentials.user = $CerberusCredentials.UserName $getUserInformationRequest.credentials.password = $CerberusCredentials.GetNetworkCredential().Password # Populate request object with the username to retrieve $getUserInformationRequest.userName = $newTestUserName # Issue the getUserInformation request [CerberusFtp.GetUserInformationResponse] $getUserInformationResponse = $CerberusSvc.getUserInformation($getUserInformationRequest)
We check the result of the response to make sure we found an existing user account:
# Check response for success or failure if (-not $getUserInformationResponse.result){ Write-Error "Failed to retrieve user: $($getUserInformationResponse.message)" } else {
Then we change the email address for this user object:
[CerberusFtp.User] $userToModify = $getUserInformationResponse.UserInformation $userToModify.email = "NewEmailAddress@powershellExample.net"
We use AddUser and its corresponding request type AddUserRequest to both create users and modify existing users. If the userName matches that of an existing user, the existing user is overwritten. We've named the request object $modifyUserRequest to express our intentions clearly:
# Populate request with modified user object [CerberusFtp.AddUserRequest] $modifyUserRequest = New-Object CerberusFtp.AddUserRequest # Populate an AddUserRequest object with the modified user object $modifyUserRequest.credentials = New-Object CerberusFtp.Credentials $modifyUserRequest.credentials.user = $CerberusCredentials.UserName $modifyUserRequest.credentials.password = $CerberusCredentials.GetNetworkCredential().Password # Copy the newly-modified user object to the $modifyUserRequest object $modifyUserRequest.User = $userToModify # Issue AddUser request to modify existing user [CerberusFtp.AddUserResponse] $modifyUserResponse = $CerberusSvc.AddUser($modifyUserRequest) # Check response for success or failure if (-not $modifyUserResponse.result){ Write-Error "Failed to update user: $($modifyUserResponse.message)" } else { Write-Host "Successfully updated email address of $($userToModify.name)" } }
Change Password of a User
The password is just another property of the User object. You could modify it in the same fashion we modified the .email property. However, password resets are frequent enough that a dedicated operation is provided. This reduces complexity of copying the whole user object from server to client and back again.
Use the ChangePassword operation along with ChangePasswordRequest:
# Create new ChangePasswordRequest object [CerberusFtp.ChangePasswordRequest] $changePasswordRequest = New-Object CerberusFtp.ChangePasswordRequest # Populate request object with Cerberus Admin credentials $changePasswordRequest.credentials = New-Object CerberusFtp.Credentials $changePasswordRequest.credentials.user = $CerberusCredentials.UserName $changePasswordRequest.credentials.password = $CerberusCredentials.GetNetworkCredential().Password # Populate with the user whose password we wish to change $changePasswordRequest.userName = $newTestUserName # Setting adminPasswordReset to true allows us to change the password without knowing the existing password $changePasswordRequest.adminPasswordReset = $true $changePasswordRequest.adminPasswordResetSpecified = $true # Populate request with the desired password $changePasswordRequest.newPassword = "ThisIsANewPassword1234!@#$"
Note that the password is sent in plain-text. It is for this reason that we always recommend using HTTPS for SOAP communication.
Note also that Cerberus FTP Server never stores passwords in plain-text. As soon as the plain-text is received, Cerberus salts and hashes the value before saving it to the user.
# Issue the ChangePassword request [CerberusFtp.ChangePasswordResponse] $changePasswordResponse = $CerberusSvc.ChangePassword($changePasswordRequest) # Check response for success or failure if (-not $changePasswordResponse.result){ Write-Error "Failed to change password: $($changePasswordResponse.message)" } else { Write-Host "Successfully changed password for $newTestUserName" }
Add Virtual Directory to a User
As with password reset, a dedicated request types are provided for adding and removing virtual directories. Provide the userName whose directories will be modified and a CerberusFtp.VirtualDirectory object. If the name of the virtual directory matches an existing one, the existing one is overwritten:
# Create a new AddDirectoryToUserRequest object [CerberusFtp.AddDirectoryToUserRequest] $addDirectoryRequest = New-Object -TypeName CerberusFtp.AddDirectoryToUserRequest # Populate request object with Cerberus Admin credentials $addDirectoryRequest.credentials = New-Object -TypeName CerberusFtp.Credentials $addDirectoryRequest.credentials.user = $CerberusCredentials.UserName $addDirectoryRequest.credentials.password = $CerberusCredentials.GetNetworkCredential().Password # Populate request object with the target username $addDirectoryRequest.userName = $newTestUserName # Create new VirtualDirectory object $addDirectoryRequest.directory = New-Object -TypeName CerberusFtp.VirtualDirectory # Populate virtual directory object with name, path, and permissions $addDirectoryRequest.directory.name = "NewRoot" $addDirectoryRequest.directory.path = "c:\testroot"
With twelve defined permissions, this section can be a little verbose:
$addDirectoryRequest.directory.permissions = New-Object -TypeName CerberusFtp.DirectoryPermissions # Grant download, upload, list files, list directories, rename, create, and delete
$addDirectoryRequest.directory.permissions.allowDownload = $true
$addDirectoryRequest.directory.permissions.allowDownloadSpecified = $true
$addDirectoryRequest.directory.permissions.allowUpload = $true
$addDirectoryRequest.directory.permissions.allowUploadSpecified = $true
$addDirectoryRequest.directory.permissions.allowListDir = $true
$addDirectoryRequest.directory.permissions.allowListFile = $true
$addDirectoryRequest.directory.permissions.allowRename = $true
$addDirectoryRequest.directory.permissions.allowRenameSpecified = $true
$addDirectoryRequest.directory.permissions.allowDirectoryCreation= $true
$addDirectoryRequest.directory.permissions.allowDelete= $true
$addDirectoryRequest.directory.permissions.allowDeleteSpecified = $true
# Issue the AddDirectoryToUser request [CerberusFtp.AddDirectoryToUserResponse] $addDirectoryResponse = $CerberusSvc.AddDirectoryToUser($addDirectoryRequest) # Check response for success or failure if (-not $addDirectoryResponse.result){ Write-Error "Failed to add virtual directory to user: $($addDirectoryResponse.message)" } else { Write-Host "Successfully added $($addDirectoryRequest.directory.name) to $newTestUserName" }
Delete a User
The last operation we demonstrate is perhaps the simplest. Provide a valid username and Cerberus FTP Server will delete the user.
# Create a new DeleteUserRequest object [CerberusFtp.DeleteUserRequest] $deleteUserRequest = New-Object -TypeName CerberusFtp.DeleteUserRequest # Populate request object with Cerberus Admin credentials $deleteUserRequest.credentials = New-Object CerberusFtp.Credentials $deleteUserRequest.credentials.user = $CerberusCredentials.UserName $deleteUserRequest.credentials.password = $CerberusCredentials.GetNetworkCredential().Password # Populate request object with username to be deleted $deleteUserRequest.name = $newTestUserName # Issue the DeleteUser request [CerberusFtp.DeleteUserResponse] $deleteUserResponse = $CerberusSvc.DeleteUser($deleteUserRequest) # Check response for success or failure if (-not $deleteUserResponse.result){ Write-Error "Failed to delete user $newTestUserName : $($deleteUserResponse.message)" } else { Write-Host "Successfully deleted $newTestUserName" }
Conclusion
That covers common operations on Cerberus native users. In the next guide we'll cover group manipulation: adding, modifying, and removing, as well as membership changes. We'll also revisit UserPropertyBool and how constraints are applied to users.
Comments
0 comments
Article is closed for comments.