Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ bld/

# Visual Studio 2015 cache/options directory
.vs/
.vscode/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,13 @@ protected override void ProcessRecord()
SessionId = this.SessionId
};
userProfileProvider.SetUserProfile(userProfile);


if (SessionIdAdapter.ValidateSessionId(this.Server, this.SessionId))
{
WriteObject($"Connected to the Cohesity Cluster {Server} Successfully");
return;
}
userProfileProvider.DeleteUserProfile();
WriteObject("Failed to connect to the Cohesity Cluster.");
return;
}

var networkCredential = Credential.GetNetworkCredential();
Expand Down
1 change: 1 addition & 0 deletions src/Cohesity.Powershell/Cohesity.PowerShell.Core.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ FunctionsToExport = @(
'New-CohesityPhysicalServerProtectionJob'
'New-CohesityProtectionPolicy',
'New-CohesityRoutes',
'New-CohesitySessionId',
'New-CohesityStorageDomain',
'New-CohesityUserGroup',
'New-CohesityVirtualIP',
Expand Down
1 change: 1 addition & 0 deletions src/Cohesity.Powershell/Cohesity.PowerShell.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ FunctionsToExport = @(
'New-CohesityPhysicalServerProtectionJob'
'New-CohesityProtectionPolicy',
'New-CohesityRoutes',
'New-CohesitySessionId',
'New-CohesityStorageDomain',
'New-CohesityUserGroup',
'New-CohesityVirtualIP',
Expand Down
107 changes: 100 additions & 7 deletions src/Cohesity.Powershell/Common/sessionidadapter.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Cohesity.Model;
using Newtonsoft.Json;

namespace Cohesity.Powershell.Common
{
class SessionIdAdapter
{
static public bool ValidateSessionId(string server, string sessionId)
public static bool ValidateSessionId(string server, string sessionId)
{
Session session = new Session();
var session = new Session();
var preparedUrl = $"/public/users";
var result = session.ApiClient.Get<IEnumerable<Model.User>>(preparedUrl);
ICollection<Model.User> users = result as ICollection<Model.User>;
if (users.Count == 0)

try
{
var result = session.ApiClient.Get<IEnumerable<Model.User>>(preparedUrl);
if (result is ICollection<Model.User> users && users.Count > 0)
{
return true;
}
}
catch (Exception ex)
{
Console.WriteLine("Exception during session regeneration: " + ex.Message);
}

return TryRegenerateSessionId(server);
}

private static bool TryRegenerateSessionId(string server)
{
var userProfileProvider = ServiceLocator.GetUserProfileProvider();
var userProfile = userProfileProvider.GetUserProfile();
var credentials = userProfileProvider.GetCredentials();

if (userProfile == null || credentials == null || userProfile.ClusterUri == null)
{
Console.WriteLine("Missing profile or credentials.");
return false;
}
return true;

try
{
var requestBody = new
{
username = credentials.Username,
password = credentials.Password
};

var clusterUri = userProfile.ClusterUri.ToString();
if (clusterUri.Contains("/irisservices/api/v1"))
{
clusterUri = clusterUri.Replace("/irisservices/api/v1", "");
}

var baseUri = new Uri(clusterUri);
var apiUri = new Uri(baseUri, "v2/users/sessions");

var httpRequest = new HttpRequestMessage(HttpMethod.Post, apiUri)
{
Content = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, "application/json")
};

var httpClient = new RestApiClient().BuildClient(userProfile.ClusterUri, true);



var response = httpClient.SendAsync(httpRequest).Result;
var content = response.Content.ReadAsStringAsync().Result;

if (response.StatusCode == HttpStatusCode.Created)
{
var sessionResponse = JsonConvert.DeserializeObject<SessionIdResponse>(content);
userProfile.SessionId = sessionResponse.SessionId;
userProfileProvider.SetUserProfile(userProfile);

Console.WriteLine("Session ID successfully regenerated.");

// Retry validation
var session = new Session();
var users = session.ApiClient.Get<IEnumerable<Model.User>>("/public/users");
return users != null && users.Any();
}
else
{
Console.WriteLine("Failed to regenerate session ID: " + content);
}
}
catch (Exception ex)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Failed to connect to the Cohesity Cluster");
sb.AppendLine(ex.Message);
throw new Exception(sb.ToString());
}

return false;
}
}

/// <summary>
/// Represents the response from the Cohesity API containing the session ID.
/// </summary>
public class SessionIdResponse
{
/// <summary>
/// The session ID returned by the Cohesity API after successful authentication.
/// </summary>
[JsonProperty("sessionId")]
public string SessionId { get; set; }
}
}
137 changes: 137 additions & 0 deletions src/Cohesity.Powershell/Scripts/User/New-CohesitySessionId.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
$Global:CohesityUserAgentName = $null
$Global:CohesityAPIError = $null

# Allow the caller to have access to response object,
# it is observed that some of the REST APIs (PUT method) do not return object,
# therefore provisioning an object, so that the caller can identify using the status code, if the API call succeeded
# Capture all response codes and the relevant error messages.
$Global:CohesityAPIStatus = $null

function New-CohesitySessionId {
<#
.SYNOPSIS
Returns the session ID For the user
.DESCRIPTION
Create the user session
.NOTES
Published by Cohesity
.LINK
https://cohesity.github.io/cohesity-powershell-module/#/README
.EXAMPLE
New-CohesitySessionId -Server 10.0.0.1 -Credential (Get-Credential)
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string[]]$Server,

[Parameter(Mandatory = $true)]
[PSCredential]$Credential,

[Parameter(Mandatory = $false)]
[string]$Domain = "LOCAL", # default domain

[Parameter(Mandatory = $false)]
[string]$OtpCode,

[Parameter(Mandatory = $false)]
[string]$OtpType
)
Enable-SelfSignedCertificates

if ($null -eq $Global:CohesityCmdletConfig) {
$Global:CohesityCmdletConfig = Get-CohesityCmdletConfig
}


$Global:CohesityAPIError = $null
try {
$username = $Credential.UserName
$password = $Credential.GetNetworkCredential().Password

$cohesitycredentials = @{
otpType = "Totp"
certificate = $null
domain = "LOCAL"
otpCode = $null
password = $password
privateKey = $null
username =$username
}
$jsonProfile = $cohesitycredentials | ConvertTo-Json -Compress -Depth 5

[Environment]::SetEnvironmentVariable("cohesityCredentials", $jsonProfile, 'Process')

$baseUri = "https://$Server"
$sessionUri = $baseUri + "/v2/users/sessions"
$sessionBody = @{
username = $Username
password = $Password
}

$jsonBody = $sessionBody | ConvertTo-Json -Compress -Depth 5

$PSBoundParameters = @{
Uri = $sessionUri
Method = 'Post'
Body = $jsonBody
}

$result = Invoke-WebRequest @PSBoundParameters

if ($result.Content) {
$parsedResponse = $result.Content | ConvertFrom-Json
$sessionId = $parsedResponse.sessionId
$cohesitySession = @{
ClusterUri = $baseUri
AllowInvalidServerCertificates = $true
AccessToken = $null
SessionId = $sessionId
ApiKey = $null
}
CohesityUserProfile -UserProfileData $cohesitySession
}
else {
$errorMsg = "Session Id was not Created"
Write-Output $errorMsg
CSLog -Message $errorMsg
}

if ($Global:CohesityCmdletConfig) {
if ($Global:CohesityCmdletConfig.LogResponseData -eq $true) {
if ($result.Content) {
Write-Host "Connected to the Cohesity Cluster $Server Successfully"
}
else {
CSLog -Message "Response content not available" -Severity 1
}
}
}


}
catch {
$Global:CohesityAPIError = $_.Exception

# Construct a serializable object with only string-based properties
$logError = @{
Message = $Global:CohesityAPIError.Message
Source = $Global:CohesityAPIError.Source
StackTrace = $Global:CohesityAPIError.StackTrace
TargetSite = "$($Global:CohesityAPIError.TargetSite)"
ParameterName = if ($Global:CohesityAPIError.PSObject.Properties["ParameterName"]) {
$Global:CohesityAPIError.ParameterName
} else {
$null
}
}

# Safe logging
CSLog -Message ($logError | ConvertTo-Json -Compress -Depth 5) -Severity 3

# Write out error to the user
$errorMsg = $_
Write-Output $errorMsg
CSLog -Message $errorMsg -Severity 3
}
}
Loading