Skip to content

Instantly share code, notes, and snippets.

@agnivesh
Created February 11, 2025 10:16
Show Gist options
  • Save agnivesh/4dfbab47d96431a5b41cb89acc31c3fa to your computer and use it in GitHub Desktop.
Save agnivesh/4dfbab47d96431a5b41cb89acc31c3fa to your computer and use it in GitHub Desktop.
# Check and install required modules
$requiredModules = @('AWS.Tools.SecretsManager', 'Posh-SSH', 'Microsoft.Graph')
foreach ($module in $requiredModules) {
if (-not (Get-Module -ListAvailable -Name $module)) {
Write-Host "Installing $module module..."
Install-Module -Name $module -Force -Scope CurrentUser
}
Import-Module $module
}
# Configuration
$config = @{
SftpServer = "your_sftp_server"
RemoteFilePath = "/path/to/remote/"
LocalDownloadPath = "C:\Downloads"
LocalCopyPath = "C:\Archive"
AwsSftpSecretName = "your_sftp_secret_name"
AwsSailPointSecretName = "your_sailpoint_secret_name"
JarFilePath = "C:\Path\To\sailpoint-file-upload-utility.jar"
SailPointUrl = "https://your-tenant.api.identitynow.com"
ObjectType = "account" # or "group" for entitlements
DisableOptimization = $false
EmailSender = "[email protected]"
EmailRecipient = "[email protected]"
}
# Function to get AWS secret
function Get-AwsSecret {
param ($secretName)
try {
$secret = Get-SECSecretValue -SecretId $secretName
return $secret.SecretString | ConvertFrom-Json
}
catch {
throw "Error retrieving AWS secret: $_"
}
}
# Function to connect to SFTP and download file
function Get-SftpFile {
param ($config, $sftpCredentials)
try {
$securePassword = ConvertTo-SecureString $sftpCredentials.Password -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential ($sftpCredentials.Username, $securePassword)
$session = New-SFTPSession -ComputerName $config.SftpServer -Credential $credentials
# Get the current date and time
$currentDate = Get-Date
# Calculate the start time for today's file (2:00 AM)
$fileStartTime = $currentDate.Date.AddHours(2)
# If current time is before 2:00 AM, look for yesterday's file
if ($currentDate -lt $fileStartTime) {
$fileStartTime = $fileStartTime.AddDays(-1)
}
# Format the filename
$fileName = "POL_TO_SAILPOINT_" + $fileStartTime.ToString("ddMMyyyyHHmmss") + ".csv"
$remoteFilePath = Join-Path $config.RemoteFilePath $fileName
# Check if the file exists
$fileExists = Test-SFTPPath -SessionId $session.SessionId -Path $remoteFilePath
if (-not $fileExists) {
throw "File $fileName not found on the SFTP server."
}
# Download the file
Get-SFTPFile -SessionId $session.SessionId -RemoteFile $remoteFilePath -LocalPath $config.LocalDownloadPath
Remove-SFTPSession -SessionId $session.SessionId
Write-Host "File $fileName downloaded successfully."
return $fileName
}
catch {
throw "Error downloading file: $_"
}
}
# Function to copy file using Robocopy
function Copy-FileWithRobocopy {
param ($config, $fileName)
try {
$robocopyArgs = @(
$config.LocalDownloadPath # Source
$config.LocalCopyPath # Destination
$fileName # File to copy
"/MOV" # Move file (delete from source after copying)
"/R:3" # Number of retries
"/W:10" # Wait time between retries
"/NFL" # No file list - don't log file names
"/NDL" # No directory list - don't log directory names
"/NP" # No progress - don't display percentage copied
)
$robocopyResult = & robocopy $robocopyArgs
$exitCode = $LASTEXITCODE
if ($exitCode -ge 8) {
throw "Robocopy encountered errors. Exit code: $exitCode"
}
else {
Write-Host "File copied successfully using Robocopy."
}
}
catch {
throw "Error copying file with Robocopy: $_"
}
}
# Function to invoke JAR file for SailPoint upload
function Invoke-JarUpload {
param ($config, $secret, $fileName)
try {
$filePath = Join-Path $config.LocalCopyPath $fileName
$jarArgs = @(
"--url", $config.SailPointUrl,
"--clientId", $secret.ClientId,
"--clientSecret", $secret.ClientSecret,
"--file", $filePath
)
if ($config.ObjectType) {
$jarArgs += "--objectType", $config.ObjectType
}
if ($config.DisableOptimization) {
$jarArgs += "--disableOptimization"
}
$output = & java -jar $config.JarFilePath $jarArgs
Write-Host "JAR file executed successfully."
return $output
}
catch {
throw "Error invoking JAR file: $_"
}
}
# Function to send email using Graph API
function Send-GraphEmail {
param (
$config,
$subject,
$body
)
try {
Connect-MgGraph -Scopes "Mail.Send"
$params = @{
Message = @{
Subject = $subject
Body = @{
ContentType = "Text"
Content = $body
}
ToRecipients = @(
@{
EmailAddress = @{
Address = $config.EmailRecipient
}
}
)
}
SaveToSentItems = "true"
}
Send-MgUserMail -UserId $config.EmailSender -BodyParameter $params
Write-Host "Email sent successfully."
}
catch {
Write-Error "Error sending email: $_"
}
}
# Main execution
try {
$sftpCredentials = Get-AwsSecret -secretName $config.AwsSftpSecretName
$fileName = Get-SftpFile -config $config -sftpCredentials $sftpCredentials
Copy-FileWithRobocopy -config $config -fileName $fileName
$sailPointSecret = Get-AwsSecret -secretName $config.AwsSailPointSecretName
$jarOutput = Invoke-JarUpload -config $config -secret $sailPointSecret -fileName $fileName
# Send success email
Send-GraphEmail -config $config -subject "File Upload Completed Successfully" -body "The file upload process has completed for file $fileName. Output: $jarOutput"
Write-Host "Script completed successfully."
}
catch {
$errorMessage = $_.Exception.Message
Write-Error "An error occurred: $errorMessage"
# Send failure email
Send-GraphEmail -config $config -subject "File Upload Process Failed" -body "An error occurred during the file upload process: $errorMessage"
}
# Check and install required modules
$requiredModules = @('AWS.Tools.SecretsManager', 'Microsoft.Graph')
foreach ($module in $requiredModules) {
if (-not (Get-Module -ListAvailable -Name $module)) {
Write-Host "Installing $module module..."
Install-Module -Name $module -Force -Scope CurrentUser
}
Import-Module $module
}
# Configuration
$config = @{
SftpServer = "your_sftp_server"
SftpPort = 22
RemoteFilePath = "/path/to/remote/"
LocalDownloadPath = "C:\Downloads"
LocalCopyPath = "C:\Archive"
WinScpPath = "C:\Program Files (x86)\WinSCP\WinSCP.com"
AwsSftpSecretName = "your_sftp_secret_name"
AwsSailPointSecretName = "your_sailpoint_secret_name"
JarFilePath = "C:\Path\To\sailpoint-file-upload-utility.jar"
SailPointUrl = "https://your-tenant.api.identitynow.com"
ObjectType = "account" # or "group" for entitlements
DisableOptimization = $false
EmailSender = "[email protected]"
EmailRecipient = "[email protected]"
}
# Function to get AWS secret
function Get-AwsSecret {
param ($secretName)
try {
$secret = Get-SECSecretValue -SecretId $secretName
return $secret.SecretString | ConvertFrom-Json
}
catch {
throw "Error retrieving AWS secret: $_"
}
}
# Function to connect to SFTP and download file using WinSCP
function Get-SftpFile {
param ($config, $sftpCredentials)
try {
# Calculate the file name
$currentDate = Get-Date
$fileStartTime = $currentDate.Date.AddHours(2)
if ($currentDate -lt $fileStartTime) {
$fileStartTime = $fileStartTime.AddDays(-1)
}
$fileName = "POL_TO_SAILPOINT_" + $fileStartTime.ToString("ddMMyyyyHHmmss") + ".csv"
$remoteFilePath = "$($config.RemoteFilePath)$fileName"
# Prepare WinSCP script
$winScpScript = @"
option batch abort
option confirm off
open sftp://$($sftpCredentials.Username):$($sftpCredentials.Password)@$($config.SftpServer):$($config.SftpPort)/ -hostkey=*
get $remoteFilePath $($config.LocalDownloadPath)
exit
"@
# Save WinSCP script to a temporary file
$tempScriptPath = [System.IO.Path]::GetTempFileName()
$winScpScript | Out-File -FilePath $tempScriptPath -Encoding ASCII
# Execute WinSCP
$winScpOutput = & $config.WinScpPath /script=$tempScriptPath
# Check for errors
if ($LASTEXITCODE -ne 0) {
throw "WinSCP encountered an error. Exit code: $LASTEXITCODE. Output: $winScpOutput"
}
# Clean up temporary script file
Remove-Item $tempScriptPath
Write-Host "File $fileName downloaded successfully."
return $fileName
}
catch {
throw "Error downloading file: $_"
}
}
# Function to copy file using Robocopy
function Copy-FileWithRobocopy {
param ($config, $fileName)
try {
$robocopyArgs = @(
$config.LocalDownloadPath # Source
$config.LocalCopyPath # Destination
$fileName # File to copy
"/MOV" # Move file (delete from source after copying)
"/R:3" # Number of retries
"/W:10" # Wait time between retries
"/NFL" # No file list - don't log file names
"/NDL" # No directory list - don't log directory names
"/NP" # No progress - don't display percentage copied
)
$robocopyResult = & robocopy $robocopyArgs
$exitCode = $LASTEXITCODE
if ($exitCode -ge 8) {
throw "Robocopy encountered errors. Exit code: $exitCode"
}
else {
Write-Host "File copied successfully using Robocopy."
}
}
catch {
throw "Error copying file with Robocopy: $_"
}
}
# Function to invoke JAR file for SailPoint upload
function Invoke-JarUpload {
param ($config, $secret, $fileName)
try {
$filePath = Join-Path $config.LocalCopyPath $fileName
$jarArgs = @(
"--url", $config.SailPointUrl,
"--clientId", $secret.ClientId,
"--clientSecret", $secret.ClientSecret,
"--file", $filePath
)
if ($config.ObjectType) {
$jarArgs += "--objectType", $config.ObjectType
}
if ($config.DisableOptimization) {
$jarArgs += "--disableOptimization"
}
$output = & java -jar $config.JarFilePath $jarArgs
Write-Host "JAR file executed successfully."
return $output
}
catch {
throw "Error invoking JAR file: $_"
}
}
# Function to send email using Graph API
function Send-GraphEmail {
param (
$config,
$subject,
$body
)
try {
Connect-MgGraph -Scopes "Mail.Send"
$params = @{
Message = @{
Subject = $subject
Body = @{
ContentType = "Text"
Content = $body
}
ToRecipients = @(
@{
EmailAddress = @{
Address = $config.EmailRecipient
}
}
)
}
SaveToSentItems = "true"
}
Send-MgUserMail -UserId $config.EmailSender -BodyParameter $params
Write-Host "Email sent successfully."
}
catch {
Write-Error "Error sending email: $_"
}
}
# Main execution
try {
$sftpCredentials = Get-AwsSecret -secretName $config.AwsSftpSecretName
$fileName = Get-SftpFile -config $config -sftpCredentials $sftpCredentials
Copy-FileWithRobocopy -config $config -fileName $fileName
$sailPointSecret = Get-AwsSecret -secretName $config.AwsSailPointSecretName
$jarOutput = Invoke-JarUpload -config $config -secret $sailPointSecret -fileName $fileName
# Send success email
Send-GraphEmail -config $config -subject "File Upload Completed Successfully" -body "The file upload process has completed for file $fileName. Output: $jarOutput"
Write-Host "Script completed successfully."
}
catch {
$errorMessage = $_.Exception.Message
Write-Error "An error occurred: $errorMessage"
# Send failure email
Send-GraphEmail -config $config -subject "File Upload Process Failed" -body "An error occurred during the file upload process: $errorMessage"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment