##/*****************************************************************************
##Author                :     MohanRaj S
##Purpose               :     Display the list of services and their operations
##Created               :     19/10/2017
##Modified By		    :     Prabaharan.T

$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
$PSDefaultParameterValues = @{'*:Encoding' = 'utf8'}

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$egurkhaPath=($scriptPath.Substring(0,$scriptPath.ToLower().IndexOf('egurkha')+7)).Trim()
$egEncryPath=$scriptPath+"\EGFileEncryption.psm1"
$egDatnKy=$scriptPath+"\GetDatnKeyFiles.psm1"
Import-Module $egEncryPath,$egDatnKy

clear
#<#
$TestInputs=$args
$userName=$TestInputs[0]
$Password=Eg-O365Dcr -EncStr $TestInputs[1]
$proxyserverip=$TestInputs[2]
$proxyUsr=$TestInputs[3]
$proxyPass=Eg-O365Dcr -EncStr $TestInputs[4]
$rpmea=$TestInputs[5]
$topN_DD=$TestInputs[6]

$rpArr=$rpmea.Split('#')
$reportingNam=$rpArr[0]
$meaperiod=$rpArr[1]
$allowLocalUsrAct=$rpArr[2]
$allowLocalUsr=$rpArr[3].Split(',')

$appDetails=$TestInputs[7]
if($appDetails -and $appDetails -ne 'none'){
    $appDetailsArr=($appDetails).ToString() -Split ("~!~")
    $clientId=$appDetailsArr[0]
    $tenantName=$appDetailsArr[1]
    $thumbPrint=$appDetailsArr[2]
}
#>

$azureVal=Eg-GetAzureEnv -UserName $userName
$azureEnvArr=$azureVal.Split(',')
$langPath=$egurkhaPath+'\agent\config\O365_lang.ini'
$encTyp=Eg-GetINIContent -Path $langPath -Subject 'File_Type' -Key 'encoding'

$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $(convertto-securestring $Password -asplaintext -force)
$sessionOption = New-PSSessionOption -SkipRevocationCheck
if(!$proxyserverip.ToString().ToLower().Contains('none')){
    $proxyserver='http://'+$proxyserverip
    [system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy($proxyserver)
    if($proxyUsr -ne 'none' -and $proxyPass -ne 'none'){
        $proxyCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $proxyUsr, $(convertto-securestring $proxyPass -asplaintext -force)
        [system.net.webrequest]::defaultwebproxy.credentials =$proxyCred
        [system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
        $sessionOption = New-PSSessionOption -SkipRevocationCheck -ProxyAccessType WinHttpConfig -ProxyAuthentication basic -ProxyCredential $proxyCred
    }
}
if($appDetails -and $appDetails -ne 'none'){
    Connect-ExchangeOnline -CertificateThumbPrint $thumbPrint -AppID $clientId -Organization $tenantName -PSSessionOption $sessionOption -ShowBanner:$false -WarningAction SilentlyContinue
}else{
    Connect-ExchangeOnline  -ExchangeEnvironmentName $azureEnvArr[4] -ConnectionUri $azureEnvArr[1] -Credential $cred -PSSessionOption $sessionOption -WarningAction SilentlyContinue
}
$rptPath='O365/'+$reportingNam
try{
    #if((Get-PSSession).Availability -eq 'Available' -and (Get-PSSession).State -eq 'Opened'){
        $sysDat=(Get-Date).ToUniversalTime()
        $endDat=$sysDat.AddMinutes(-60)
        $startDat=$endDat.AddMinutes(-$meaperiod)
        $uniqwrkLoad=@{}
        $uniqUserClientIpwrkLoad=@{}
	$uniqClientIp=@{}
        Try{
            $writUsrAct = Eg-WriteFile -ComntRptPath $rptPath -FileName "O365UsrAct" -keyFileName "kO365UsrAct" -EgPath $egurkhaPath
            $curResCnt=0
            while($true){
                $results=Search-UnifiedAuditLog -StartDate $startDat -EndDate $endDat -SessionId ua -SessionCommand ReturnLargeSet -ResultSize 5000 |Select-Object  CreationDate,AuditData
                $results | Export-Csv $writUsrAct[1] -Append -Encoding $encTyp
                $curResCnt=$curResCnt+($results.count)
                if(($curResCnt -eq 50000) -or ($results.count -lt 5000)){
                    break
                }
            }
            $null=Protect-File  $writUsrAct[1] -Algorithm AES -KeyAsPlainText $writUsrAct[0] -RemoveSource
        }Catch{
	          $egurkhaRprtPath=  $egurkhaPath+'\agent\'+$rptPath+'\'
          $fileRead=Get-ChildItem -Path $egurkhaRprtPath |Where-Object {$_.Name -like 'kO365UsrAct*.dat'}| Sort-Object LastWriteTime -Descending | Select Name -First 1
            foreach($file in $fileRead){
                    $fileName=([String]$file.Name).Trim()
                    if([System.IO.File]::Exists(($egurkhaRprtPath+$fileName)) -eq 'True'){
                        Remove-Item $egurkhaRprtPath$fileName -Force
                    }
            }
	    }
        try{
            $readUsrAct=Eg-ReadFile -ComntRptPath $rptPath -FileName "O365UsrAct" -keyFileName "kO365UsrAct" -EgPath $egurkhaPath
            if($readUsrAct -ne $null -and [System.IO.File]::Exists($readUsrAct[1]) -eq 'True'){
                $unProtctUsrAct=$readUsrAct[1] -replace (".csv",".dat") 
                $usrActPath=Unprotect-File $unProtctUsrAct -Algorithm AES -KeyAsPlainText $readUsrAct[0]	
                $a= import-csv $usrActPath -Encoding $encTyp
                Remove-Item $usrActPath
                Eg-DeleteFiles -FilePath $readUsrAct[2] -Pattern 'O365UsrAct' -InputFile $readUsrAct[3]
                Eg-DeleteFiles -FilePath $readUsrAct[2] -Pattern 'kO365UsrAct' -InputFile $readUsrAct[4]
            }
            [System.GC]::GetTotalMemory($true) | out-null
        }
        catch{
            $errmsg=$_.Exception.Message
            Write-Error -Message $errmsg
        }
        $UniqueClientIp=@()
        $UniqueUserId=@()
        $ExcludeActv='FileAccessed','FileCheckedIn','FileCheckedOut','FileCopied','FileDeleted','FileDeletedFirstStageRecycleBin','FileDeletedSecondStageRecycleBin','FileCheckOutDiscarded','FileDownloaded','FileModified','FileMoved','FileRenamed','FileRestored','FileUploaded','PageViewed','Search-Mailbox','UserLoggedIn','UserLoginFailed'        
        foreach($b in $a){
            try{
                $activity = $b.AuditData | ConvertFrom-Json | select Workload,Operation,UserId,ClientIP
                if($activity -match '::1' -or $activity -match '<null>' -or $activity.UserId -eq 'Not Available'){
                   continue
                }
            }catch{
            }
            $entryflag=$true
            if($allowLocalUsrAct -eq $true){
                if($allowLocalUsr -contains($activity.UserId) -and $ExcludeActv -contains($activity.Operation)){
                    $entryflag=$true
                }
            }
            else{
                if($allowLocalUsr -contains($activity.UserId) -and $ExcludeActv -contains($activity.Operation)){
                    $entryflag=$false
                }
            }
            if($entryflag -and $activity -ne "" -and $activity -ne $null -and $activity.ClientIP -ne $null){
	    		if($activity.ClientIP -ne ""){
				    $ClientIp=$activity.ClientIP
			    }else{
				    continue
			    }

           		$charCount=( $ClientIp.ToCharArray() | Where-Object {$_ -eq ':'} | Measure-Object).Count 
			    if($charCount -eq 1){
			        $ClientIp=$activity.ClientIP.Split(':')[0]
			        $ClientIp=$ClientIp.Replace("[","").Replace("]","")
			    }
			    $ClientIp=$ClientIp.Trim()
			    $uniqwrkLoadkey  = $activity.Workload+'~'+$activity.Operation.Replace(" ","_")
			    $uniqClientIpkey = $activity.Workload+'~'+$ClientIp
			    $ClientIpInnerKey= $activity.UserId+'~'+$ClientIp+'~'+$activity.Operation.Replace(" ","_")
			    $uniqUserIdkey   = $activity.Workload+'~'+$activity.UserId
			    $userIdInnerKey  = $ClientIp+'~'+$activity.UserId+'~'+$activity.Operation.Replace(" ","_")
                if(-not $UniqueUserId.Contains($activity.UserId.ToLower())){
                    $UniqueUserId+=$activity.UserId.ToLower()
                }
                if(-not $UniqueClientIp.Contains($ClientIp)){
                    $UniqueClientIp+=$ClientIp
                }
			    # Total Operations
		
			    if($uniqwrkLoad.ContainsKey($uniqwrkLoadkey)){
			        $uniqwrkLoad[$uniqwrkLoadkey]=[int]$uniqwrkLoad[$uniqwrkLoadkey]+1
			    }else{
			        $uniqwrkLoad.Add($uniqwrkLoadkey,1) 
			    }

                if($uniqUserClientIpwrkLoad.ContainsKey($activity.Workload)){
                    $tmpArray=$uniqUserClientIpwrkLoad[$activity.Workload]
                    if(-not $tmpArray[0].Contains($activity.UserId)){
                        $tmpArray[0]+=" "+$activity.UserId
                    }
                    if(-not $tmpArray[1].Contains($ClientIp)){
                        $tmpArray[1]+=" "+$ClientIp
                    }
			    }else{
                    [String[]]$myArray =$activity.UserId,$ClientIp
			        $uniqUserClientIpwrkLoad.Add($activity.Workload,$myArray)
			    }

                

			    # Client Ip

			    if($uniqClientIp.ContainsKey($activity.Workload)){
			        $tmpht=$uniqClientIp[$activity.Workload]
			        if($tmpht.ContainsKey($userIdInnerKey)){
				    $tmpht[$userIdInnerKey]=[int]$tmpht[$userIdInnerKey]+1
			        }else{
				    $tmpht.Add($userIdInnerKey,1)
			        }
			    }
			    else{
			        $tmpuniqClientIp = @{}
			        $tmpuniqClientIp.Add($userIdInnerKey,1)
			        $uniqClientIp.Add($activity.Workload,$tmpuniqClientIp) 
			    }
            }
        }
    $totOpr=0
    foreach($key in $uniqwrkLoad.keys){
        Write-Host 'Audit~' $key '~' $uniqwrkLoad[$key]
        $totOpr+=$uniqwrkLoad[$key]
    }

    foreach($key in $uniqUserClientIpwrkLoad.keys){
        Write-Host 'UsersCount~' $key '~' ($uniqUserClientIpwrkLoad[$key][0].Split(" ").Length)'~' ($uniqUserClientIpwrkLoad[$key][1].Split(" ").Length)
    }

    Write-Host 'Summary~' $totOpr ~ $uniqwrkLoad.Count ~ ($UniqueUserId | select -unique).Count ~ ($UniqueClientIp| select -unique).Count
    foreach($key in $uniqClientIp.keys){
        $uniqInnerht=$uniqClientIp[$key]
        $ipList = New-Object Collections.Generic.List[String]
        $userList = New-Object Collections.Generic.List[String]
		$in =$uniqInnerht.keys | sort { $uniqInnerht.$_ } -des
		foreach($inky in $in) {
            if($ipList.Count -ge [int]$topN_DD -and $userList.Count -ge [int]$topN_DD) {
                break;
            }
            $tokens = $inky.Split('~')
            if($ipList -notcontains $tokens[0]) {
                $ipList.Add($tokens[0])
            }
            if($userList -notcontains $tokens[1]) {
                $userList.Add($tokens[1])
            }
            Write-host 'DDAudit~' $key '#' $inky  '['$uniqInnerht[$inky]']'
        }
    }
#}
$getSession=Get-PSSession -ErrorAction SilentlyContinue
if($getSession -ne $null -and $getSession -ne ''){
	Disconnect-ExchangeOnline -Confirm:$false
}
}catch
{    
	Write-Host 'Exception Occured in O365 UserActivity - ' $_.Exception.Message 
}
[System.GC]::GetTotalMemory($true) | out-null