通过 PowerShell 脚本比较两个工具中的服务器 ID
Comparing Server IDs in two tools via PowerShell script
我正在制作一个 PowerShell 脚本,用于检索和比较我们正在使用的两个工具中的服务器 ID - Octopus 工具和 MOSS(目的是检查 Octopus 中的所有服务器是否也在 MOSS 中注册) .通过 MySQL 查询在 PowerShell 上访问 Octopus,通过 API 调用访问 MOSS。目前我能够成功检索 sql 查询并将其格式化为 JSON 以便 MOSS 能够读取。但是,我不知道如何检查服务器 ID 是否也存在于 MOSS 中。该脚本所做的只是从 Octopus SQL 中检索 ID,然后将它们解析为 JSON 并对 MOSS 进行空调用。如果有人知道如何从 PowerShell 进行 MOSS 调用,将不胜感激。
当前脚本是:
# Extract RDS and servers from Octopus
# Define log file path
$date = $(get-date).tostring()
$currentdate = get-date -format yyyy-MM-dd
$log_file_path = "C:\Program Files\test\logs\"+$currentdate+"_extract_rds_and_servers_from_octopus.log"
$errorlog_file_path = "C:\Program Files\test\logs\errors\errors.log"
# 0. Exclude Admin Users before getting the RDS licenses which need to be reported
#& ((Split-Path $MyInvocation.InvocationName) + "\exclude_users.ps1") -log_file_path $log_file_path -errorlog_file_path $errorlog_file_path
# 1. Extract ObjectID from Octopus API for current month for each RDP user
try {
$month = (Get-Date -UFormat "%Y%m")
$UrlHost = "https://octopus.mos-windows.eu01.stackit.cloud/api/workspace/55cd5c70-d188-4ac3-b946-f1afec8764ad/report/licensing/spla-usage-reseller?&payload[month_id]=$month&payload[with_itemized]=1&_format=json&_token=j8FE4wZDmBITewHUc7lyYeX9XVVjt3dqz0ID4S6A9KQjkMeKfO7_EcgV7Qshuuw1&_tenant=TlXcM&_language=en&payload[flat_structure]=1"
$HostResponse = Invoke-RestMethod -Uri $UrlHost -Method Get
$users = $HostResponse.itemized
$objectids = @()
foreach ($user in $users.PSObject.Properties) {
if ($user.Value.readable_label -eq "Windows Server Remote Desktop Services")
{
$objectid = $user.Value.object_id
$objectids += $objectid
}
}
}
catch {
$date+" - Error in Octopus API Call: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# 2. Get access device ids from Octopus Database
Import-Module -Name "C:\Program Files\test\request_database.ps1" -ArgumentList $log_file_path, $errorlog_file_path -Verbose
$get_users_devices_query =
@"
select user_id, access_device_ids from oc_reporter.ws_installed_software where user_id is not null;
"@
$ui_ad = execute_db_query $get_users_devices_query
$access_device_ids = $users_devices.access_device_ids
$user_ids = $users_devices.user_id
# 3. Get all openstack server id from Octopus Database
$get_access_device_server_ids_query =
@"
select id, lower(SUBSTRING_INDEX(SUBSTRING_INDEX(ref_id, "-", -6), "-", 5)) as server_id, ref_id, label from ws_device
where type_id = "vm" and operating_system like "%Windows%" and created > 1644820951;
"@
$ad_si = execute_db_query $get_access_device_server_ids_query
# 4. Map the users/objectids with access device ids and server ids
# Create array with UserID filtered by ObjectID and map each AccessDeviceID(s) to corresponding ServerID
try {
$filteredsi = @()
foreach ($userid in $ui_ad)
{
if ($objectids -contains $userid.user_id)
{
$filteredad = $userid
foreach ($id in $ad_si)
{
if ($filteredad.access_device_ids.split(',') -contains $id.id)
{
$filteredsi += [PSCustomObject]@{"userid" = $filteredad.user_id; "serverid" = $id.server_id}
}
}
}
}
}
catch {
$date+" - Error in Mapping userIDs/objectIDs/accessdeviceIDs/serverIDs: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# Preparation for MOSS
# Create JSON contentblock with looped $filteredsi array
try {
$myArray = $filteredsi
$uniqueUsers = [System.Collections.ArrayList]::new()
for($i = 0; $i -lt $myArray.Count; $i++){
if(!$uniqueUsers.Contains($myArray[$i].userid)){
$uniqueUsers.Add($myArray[$i].userid)
}
}
$allMappings = [System.Collections.ArrayList]::new()
for($i = 0; $i -lt $uniqueUsers.Count; $i++){
$singleMapping = [PSCustomObject]@{id = $uniqueUsers[$i]; servers = $null}
$serverids = [System.Collections.ArrayList]::new()
for($j = 0; $j -lt $myArray.Count; $j++){
if($myArray[$j].userid -eq $uniqueUsers[$i]){
$serverids.Add($myArray[$j].serverid)
}
}
$singleMapping.servers = $serverids
$allMappings.Add($singleMapping)
}
$mosscontent = $allMappings | ConvertTo-Json
$mosscontent
}
catch {
$date+" - Error in creating content block for MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# Create complete array including contentblock for MOSS API call
try {
$moss = @"
{
"type": "server.usage",
"data": {
"users": $mosscontent
}
}
"@
}
catch {
$date+" - Error in creating array for POST to MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# 5. Call MOSS prod, dev and qa with the whole list of servers and users
# Authenticating to MOSS
$query_file_path_dev_pw = "~\Documents\MOSSDevEncryptedPassword_"
$query_file_path_qa_pw = "~\Documents\MOSSQaEncryptedPassword_"
$query_file_path_prod_pw = "~\Documents\MOSSProdEncryptedPassword_"
# Function to store credentials
function get_encrypted_content {
param (
[String] $file_path,
[String] $password
)
# Check if credentials file exis
if ( -Not (Test-Path -Path $file_path)) {
switch ($password) {
dev {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-dev-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
qa {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-qa-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
prod {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-prod-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
}
}
# Read credentials from file
$Encrypted_value = Get-Content -Path $file_path
# Decrypt credentials from file
return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))
}
# Define username and password
$clientid_dev = "mos-windows-us-dev"
$clientid_qa = "mos-windows-us-qa"
$clientid_prod = "mos-windows-us-prod"
$dev_pass = get_encrypted_content $query_file_path_dev_pw "dev"
$qa_pass = get_encrypted_content $query_file_path_qa_pw "qa"
$prod_pass = get_encrypted_content $query_file_path_prod_pw "prod"
[System.Security.SecureString]$clientsecret_dev = ConvertTo-SecureString -String $dev_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_qa = ConvertTo-SecureString -String $qa_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_prod = ConvertTo-SecureString -String $prod_pass -AsPlainText -Force
#Prepare static variables
$MOSSToken_dev = 'https://auth.00.idp.eu01.stackit.cloud/oauth/token'
$MOSSToken_qa = 'https://auth.01.idp.eu01.stackit.cloud/oauth/token'
$MOSSToken_prod = 'https://auth.01.idp.eu01.stackit.cloud/oauth/token'
$MOSSUrl_dev = "https://stackit-service-mos-dev.apps.01.cf.eu01.stackit.cloud/v1/events"
$MOSSUrl_qa = "https://stackit-service-mos-qa.apps.01.cf.eu01.stackit.cloud/v1/events"
$MOSSUrl_prod = "https://stackit-service-mos.apps.01.cf.eu01.stackit.cloud/v1/events"
$body = @{grant_type='client_credentials'}
#Set function to get all customerinfo from all portals
function call_moss {
param (
[String] $clientid,
[SecureString] $clientsecret,
[String] $MOSSToken,
[String] $MOSSUrl
)
$cred = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $clientid, $clientsecret
#Get Token from MOSS
$Response = Invoke-RestMethod -Uri $MOSSToken -Method Post -Credential $cred -Body $body -ContentType "application/x-www-form-urlencoded"
$Token = $Response.access_token
$Tokenfinal = "Bearer " + $Token
#Post Content to MOSS
Invoke-RestMethod -Uri $MOSSUrl -Method Post -Headers @{'Authorization' = $Tokenfinal } -Body $moss -ContentType "application/json"
}
#Call function to Call MOSS
try
{
Write-Host "Call to MOSS Dev.."
call_moss $clientid_dev $clientsecret_dev $MOSSToken_dev $MOSSUrl_dev
Write-Host "Call to MOSS QA.."
call_moss $clientid_qa $clientsecret_qa $MOSSToken_qa $MOSSUrl_qa
Write-Host "Call to MOSS Prod"
call_moss $clientid_prod $clientsecret_prod $MOSSToken_prod $MOSSUrl_prod
}
catch
{
$date+" - Error in calling MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# 6. Create daily logs with users reported to MOSS
$date = $(get-date).tostring()
$log = foreach ($item in $filteredsi)
{
$item
}
echo $date $log | Out-file -Append $log_file_path
# delete logs older than 60 days
$limit = (Get-Date).AddDays(-60)
$path = "C:\Program Files\test\logs"
# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
# Create activity file to check if script is working
$temp_file_path = "C:\Program Files\test\tempfile*"
if (Test-Path $temp_file_path)
{
Remove-Item $temp_file_path
}
[string]$filePath = "C:\Program Files\test\tempfile";
[string]$directory = [System.IO.Path]::GetDirectoryName($filePath);
[string]$strippedFileName = [System.IO.Path]::GetFileNameWithoutExtension($filePath);
[string]$extension = [System.IO.Path]::GetExtension($filePath);
[string]$newFileName = $strippedFileName + "_" + (Get-Date).ToString('MM-dd-yyyy') + $extension;
[string]$newFilePath = [System.IO.Path]::Combine($directory, $newFileName);
New-Item $newFilePath
正在调用的其他脚本:
-> request_database.ps1
# 1. Get path for log files
param(
[string]$log_file_path = "C:\Program Files\test\logs\request_database.log",
[string]$errorlog_file_path = "C:\Program Files\test\logs\request_database_errors.log"
)
# 2. Get credentials to access Octopus DB
try {
# Define username and password security string files
$mysql_user_file_path = "~\Documents\ue_"
$mysql_pass_file_path = "~\Documents\pe_"
# Functions
function get_encrypted_content {
param (
[String] $file_path,
[String] $user_or_pass
)
# Check if credentials file exist
if ( -Not (Test-Path -Path $file_path)) {
switch ($user_or_pass) {
msqu {
# Get credentials
Read-Host -Prompt "Please, enter MySQL username" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
msqp {
# Get credentials
Read-Host -Prompt "Please, enter MySQL password" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
}
}
# Read credentials from file
$Encrypted_value = Get-Content -Path $file_path
# Decrypt credentials from file
return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))
}
# Define username and password
$my_sql_user = get_encrypted_content $mysql_user_file_path "msqu"
$my_sql_pass = get_encrypted_content $mysql_pass_file_path "msqp"
[System.Security.SecureString]$SecPwd = ConvertTo-SecureString -String $my_sql_pass -AsPlainText -Force
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist @($my_sql_user,$SecPwd)
}
catch {
$(get-date).tostring() +" - Error in fetching SQL user/pwd: "+$_ | Out-File -Append $errorlog_file_path
exit
}
$error_string = ""
# 3. Execute DB query
# If you want the script to continue on error you have to provide $true as second parameter
# Example: execute_db_query $exclude_stackitadmin_users_query $true
function execute_db_query {
param (
[String] $query,
[bool] $continueOnError = $false
)
try {
# Query Octopus DB
Connect-MySqlServer -Credential $Credential -Server localhost
if ($continueOnError) {
$query_results = Invoke-MySqlQuery -Query $query
} else {
$query_results = Invoke-MySqlQuery -Query $query -ErrorAction Stop
}
Disconnect-MySqlServer
return $query_results
}
catch {
$error_message = $(get-date).tostring() + " - Error in DB Query 1: " + $_
$error_message | Out-File -Append $errorlog_file_path
Write-Error $error_message
exit
}
}
-> exclude_users.ps1(任务可能不需要,但没有它整个脚本将无法运行)
# 1. Get path for log files or use default
param(
[string]$log_file_path = "C:\Program Files\test\logs\exclude_users.log",
[string]$errorlog_file_path = "C:\Program Files\test\logs\errors\exclude_users_errors.log"
)
Import-Module -Name "C:\Program Files\test\request_database.ps1" -ArgumentList $log_file_path, $errorlog_file_path -Verbose
# Exclude StackitAdmin users
$exclude_stackitadmin_users_query =
@"
update oc_reporter.ws_user as updated_user,
(
select id from oc_reporter.ws_user
where username = "StackITAdmin" and exclude_spla = "no"
) as us
set
exclude_spla = "yes",
exclude_spla_reason = "nh"
where updated_user.id = us.id;
"@
execute_db_query($exclude_stackitadmin_users_query)
# Exclude users on dev & qa environment
$exclude_users_on_dev_qa_query =
@"
update oc_reporter.ws_installed_software as updated_software,
(
select ws.access_device_ids, min(ws.access_device_labels), min(ws.user_label), excluded_users, min(ws.id) as id from oc_reporter.ws_user
join oc_reporter.ws_installed_software as ws
on ws.user_id = ws_user.id
join oc_reporter.ws_customer as wc
on wc.id = ws_user.customer_id
left join
(select access_device_ids, count(1) as excluded_users from oc_reporter.ws_user as wu
join oc_reporter.ws_customer as wc
on wc.id = wu.customer_id
join oc_reporter.ws_installed_software as ws
on ws.user_id = wu.id
where
(internal_id like "d-%" or internal_id like "q-%") and
locate(',', access_device_ids) = 0 and
ws.exclude_spla = "yes" and
ws.label = "Microsoft Remote Desktop Services" and
wu.username != "StackitAdmin"
group by access_device_ids, wu.exclude_spla) as servers
on servers.access_device_ids = ws.access_device_ids
where
ws.exclude_spla = "no" and
ws.label = "Microsoft Remote Desktop Services" and
(internal_id like "d-%" or internal_id like "q-%") and
locate(',', ws.access_device_ids) = 0
group by ws.access_device_ids
having (excluded_users = 1 or excluded_users is null)
) as us
set
exclude_spla = "yes",
exclude_spla_reason = "admin"
where updated_software.id = us.id;
"@
# run twice to exlude 2 users per vm
execute_db_query($exclude_users_on_dev_qa_query)
execute_db_query($exclude_users_on_dev_qa_query)
# Exclude users from our mos-windows-2 project
$exclude_users_from_our_projects =
@"
update oc_reporter.ws_installed_software as ins,
(
select ws.access_device_ids, min(ws.access_device_labels), min(ws.user_label), excluded_users, min(ws.id) as id, min(wu.id) from oc_reporter.ws_user as wu
join oc_reporter.ws_installed_software as ws
on ws.user_id = wu.id
join oc_reporter.ws_device as wd
on wd.id = ws.access_device_ids
left join (
select ws.access_device_ids, min(ws.id), min(wu.id), count(1) as excluded_users from oc_reporter.ws_user as wu
join oc_reporter.ws_installed_software as ws
on ws.user_id = wu.id
join oc_reporter.ws_device as wd
on wd.id = ws.access_device_ids
where
ws.exclude_spla = "yes" and
ws.label = "Microsoft Remote Desktop Services" and
LOCATE(',',access_device_ids) = 0 and
(
hkey like "%d57abb0200304506879bd8037f7a49cb%" or
hkey like "%fce60e2c938c49e4a37687492a45b652%" or
hkey like "%8eb91d45f25b45978b71abb0e06a0443%" or
hkey like "%66ad75e4ff624f7e940dc363549c8404%" or
hkey like "%351aa84fb9b54be896112b36ae15dd48%" or
hkey like "%64edd6c19e17417d86094e6a02610eed%"
) and
wu.username != "StackitAdmin"
group by ws.access_device_ids
) as excluded_ws
on
excluded_ws.access_device_ids = ws.access_device_ids
where
ws.exclude_spla = "no" and
ws.label = "Microsoft Remote Desktop Services" and
LOCATE(',',ws.access_device_ids) = 0 and
(
hkey like "%d57abb0200304506879bd8037f7a49cb%" or
hkey like "%fce60e2c938c49e4a37687492a45b652%" or
hkey like "%8eb91d45f25b45978b71abb0e06a0443%" or
hkey like "%66ad75e4ff624f7e940dc363549c8404%" or
hkey like "%351aa84fb9b54be896112b36ae15dd48%" or
hkey like "%64edd6c19e17417d86094e6a02610eed%"
) and
wu.domain not like "%HOP01%" and
wu.domain not like "%WSUS01%" and
wu.domain not like "%OCKMS%" and
wu.domain not like "%AZDVOP%"
group by ws.access_device_ids
having (excluded_users = 1 or excluded_users is null)
) as rds
set
exclude_spla = "yes",
exclude_spla_reason = "admin"
where ins.id = rds.id;
"@
# run twice to exlude 2 users per vm
execute_db_query($exclude_users_from_our_projects)
execute_db_query($exclude_users_from_our_projects)
顺序错误,还有很多不必要的元素导致错误和崩溃。
当前的工作代码是:
# Compare the data between the MOSS and the Octopus
# Define log file path
$date = $(get-date).tostring()
$currentdate = get-date -format yyyy-MM-dd
$log_file_path = "[FILE PATH]"
$errorlog_file_path = "[FILE PATH]"
# 1. Call MOSS (dev, qa, prod) to get the data for all servers created in the last 48 hours
# Authenticating to MOSS
$query_file_path_dev_pw = "[FILE PATH]"
$query_file_path_qa_pw = "[FILE PATH]"
$query_file_path_prod_pw = "[FILE PATH]"
# Function to store credentials
function get_encrypted_content {
param (
[String] $file_path,
[String] $password
)
# Check if credentials file exis
if ( -Not (Test-Path -Path $file_path)) {
switch ($password) {
dev {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-dev-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
qa {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-qa-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
prod {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-prod-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
}
}
# Read credentials from file
$Encrypted_value = Get-Content -Path $file_path
# Decrypt credentials from file
return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))
}
# Define username and password
$clientid_dev = "[USERNAME]"
$clientid_qa = "[USERNAME]"
$clientid_prod = "[USERNAME]"
$dev_pass = get_encrypted_content $query_file_path_dev_pw "dev"
$qa_pass = get_encrypted_content $query_file_path_qa_pw "qa"
$prod_pass = get_encrypted_content $query_file_path_prod_pw "prod"
[System.Security.SecureString]$clientsecret_dev = ConvertTo-SecureString -String $dev_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_qa = ConvertTo-SecureString -String $qa_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_prod = ConvertTo-SecureString -String $prod_pass -AsPlainText -Force
# Time variable
$date48h = ("{0:yyyy-MM-ddThh:mm:ss}" -f ((get-date).Addhours(-48))).split("T").split(":")
$date = $date48h[0]
$hour = $date48h[1]
$min = $date48h[2]
$sec = $date48h[3]
#Prepare static variables
$MOSSToken_dev = '[URL]'
$MOSSToken_qa = '[URL]'
$MOSSToken_prod = '[URL]'
$MOSSUrl_dev = "[URL]"
$MOSSUrl_qa = "[URL]"
$MOSSUrl_prod = "[URL]"
$body = @{grant_type='client_credentials'}
#Set function to get all customerinfo from all portals
function call_moss {
param (
[String] $clientid,
[SecureString] $clientsecret,
[String] $MOSSToken,
[String] $MOSSUrl
)
$cred = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $clientid, $clientsecret
#Get Token from MOSS
$Response = Invoke-RestMethod -Uri $MOSSToken -Method Post -Credential $cred -Body $body -ContentType "application/x-www-form-urlencoded"
$Token = $Response.access_token
$Tokenfinal = "Bearer " + $Token
#Post Content to MOSS
Invoke-RestMethod -Uri $MOSSUrl -Method Get -Headers @{'Authorization' = $Tokenfinal } -ContentType "application/json"
}
#Call function to Call MOSS
try
{
Write-Host "Call to MOSS Dev.."
$get_moss_dev = call_moss $clientid_dev $clientsecret_dev $MOSSToken_dev $MOSSUrl_dev
Write-Host "Call to MOSS QA.."
$get_moss_qa = call_moss $clientid_qa $clientsecret_qa $MOSSToken_qa $MOSSUrl_qa
Write-Host "Call to MOSS Prod"
$get_moss_prod = call_moss $clientid_prod $clientsecret_prod $MOSSToken_prod $MOSSUrl_prod
}
catch
{
$date+" - Error in calling MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
$moss_dev_serverids = $get_moss_dev.items.id
$moss_qa_serverids = $get_moss_qa.items.id
$moss_prod_serverids = $get_moss_prod.items.id
$moss_serverid_arr = @($moss_dev_serverids, $moss_qa_serverids, $moss_prod_serverids)
# 2. Call Octopus to get the data for new servers created in the last 36 hours
Import-Module -Name "[FILE PATH]" -ArgumentList $log_file_path, $errorlog_file_path -Verbose
# Calculate timestamp
$DateTime = Get-Date #or any other command to get DateTime object
$CurrentUnixTime = ([DateTimeOffset]$DateTime).ToUnixTimeSeconds()
$queryTime = $CurrentUnixTime - (36 * 3600)
$get_new_servers_query_oc =
@"
select id, lower(SUBSTRING_INDEX(SUBSTRING_INDEX(ref_id, "-", -6), "-", 5)) as server_id, ref_id, label from oc_reporter.ws_device where type_id = "vm" and operating_system like "%Windows%" and created > $queryTime;
"@
$query = execute_db_query $get_new_servers_query_oc
$serverid_oc = $query.server_id
$serverid_oc_arr = @($serverid_oc)
# 3. Compare the properties in MOSS and Octopus
$unmatching_serverids = $serverid_oc_arr | Where {$moss_serverid_arr -NotContains $_}
$error_report = @($unmatching_serverids)
# Create daily logs with servers in Octopus that are unregistered in MOSS
$date = $(get-date).tostring()
$log = $error_report
echo $date $log | Out-file -Append $log_file_path
# delete logs older than 60 days
$limit = (Get-Date).AddDays(-60)
$path = "[FILE PATH]"
# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
# 4. Generate summary with all errors and send a notification if there is an error. Schedule a task to check once per day.
If ($error_report.Count -eq 0) {
exit
}
else {
$JSONBody = [PSCustomObject][Ordered] @{
"type" = "MessageCard"
"title" = "Octopus Alerts"
"text" = "Servers located in Octopus, that are not registered in MOSS. <br>
Please check logs."
}
$TeamsMessageBody = ConvertTo-Json $JSONBody
$parameters = @{
"URI" = '[URL]'
"Method" = 'POST'
"Body" = $TeamsMessageBody
"ContentType" = 'application/json'
}
Invoke-RestMethod @parameters
}
# Create activity file to check if script is working
$temp_file_path = "[FILE PATH]"
if (Test-Path $temp_file_path)
{
Remove-Item $temp_file_path
}
[string]$filePath = "[FILE PATH]";
[string]$directory = [System.IO.Path]::GetDirectoryName($filePath);
[string]$strippedFileName = [System.IO.Path]::GetFileNameWithoutExtension($filePath);
[string]$extension = [System.IO.Path]::GetExtension($filePath);
[string]$newFileName = $strippedFileName + "_" + (Get-Date).ToString('MM-dd-yyyy') + $extension;
[string]$newFilePath = [System.IO.Path]::Combine($directory, $newFileName);
New-Item $newFilePath
此外,如前所述,完全不需要 exclude_users 脚本。唯一额外包含的脚本是 request_database 脚本。
我正在制作一个 PowerShell 脚本,用于检索和比较我们正在使用的两个工具中的服务器 ID - Octopus 工具和 MOSS(目的是检查 Octopus 中的所有服务器是否也在 MOSS 中注册) .通过 MySQL 查询在 PowerShell 上访问 Octopus,通过 API 调用访问 MOSS。目前我能够成功检索 sql 查询并将其格式化为 JSON 以便 MOSS 能够读取。但是,我不知道如何检查服务器 ID 是否也存在于 MOSS 中。该脚本所做的只是从 Octopus SQL 中检索 ID,然后将它们解析为 JSON 并对 MOSS 进行空调用。如果有人知道如何从 PowerShell 进行 MOSS 调用,将不胜感激。
当前脚本是:
# Extract RDS and servers from Octopus
# Define log file path
$date = $(get-date).tostring()
$currentdate = get-date -format yyyy-MM-dd
$log_file_path = "C:\Program Files\test\logs\"+$currentdate+"_extract_rds_and_servers_from_octopus.log"
$errorlog_file_path = "C:\Program Files\test\logs\errors\errors.log"
# 0. Exclude Admin Users before getting the RDS licenses which need to be reported
#& ((Split-Path $MyInvocation.InvocationName) + "\exclude_users.ps1") -log_file_path $log_file_path -errorlog_file_path $errorlog_file_path
# 1. Extract ObjectID from Octopus API for current month for each RDP user
try {
$month = (Get-Date -UFormat "%Y%m")
$UrlHost = "https://octopus.mos-windows.eu01.stackit.cloud/api/workspace/55cd5c70-d188-4ac3-b946-f1afec8764ad/report/licensing/spla-usage-reseller?&payload[month_id]=$month&payload[with_itemized]=1&_format=json&_token=j8FE4wZDmBITewHUc7lyYeX9XVVjt3dqz0ID4S6A9KQjkMeKfO7_EcgV7Qshuuw1&_tenant=TlXcM&_language=en&payload[flat_structure]=1"
$HostResponse = Invoke-RestMethod -Uri $UrlHost -Method Get
$users = $HostResponse.itemized
$objectids = @()
foreach ($user in $users.PSObject.Properties) {
if ($user.Value.readable_label -eq "Windows Server Remote Desktop Services")
{
$objectid = $user.Value.object_id
$objectids += $objectid
}
}
}
catch {
$date+" - Error in Octopus API Call: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# 2. Get access device ids from Octopus Database
Import-Module -Name "C:\Program Files\test\request_database.ps1" -ArgumentList $log_file_path, $errorlog_file_path -Verbose
$get_users_devices_query =
@"
select user_id, access_device_ids from oc_reporter.ws_installed_software where user_id is not null;
"@
$ui_ad = execute_db_query $get_users_devices_query
$access_device_ids = $users_devices.access_device_ids
$user_ids = $users_devices.user_id
# 3. Get all openstack server id from Octopus Database
$get_access_device_server_ids_query =
@"
select id, lower(SUBSTRING_INDEX(SUBSTRING_INDEX(ref_id, "-", -6), "-", 5)) as server_id, ref_id, label from ws_device
where type_id = "vm" and operating_system like "%Windows%" and created > 1644820951;
"@
$ad_si = execute_db_query $get_access_device_server_ids_query
# 4. Map the users/objectids with access device ids and server ids
# Create array with UserID filtered by ObjectID and map each AccessDeviceID(s) to corresponding ServerID
try {
$filteredsi = @()
foreach ($userid in $ui_ad)
{
if ($objectids -contains $userid.user_id)
{
$filteredad = $userid
foreach ($id in $ad_si)
{
if ($filteredad.access_device_ids.split(',') -contains $id.id)
{
$filteredsi += [PSCustomObject]@{"userid" = $filteredad.user_id; "serverid" = $id.server_id}
}
}
}
}
}
catch {
$date+" - Error in Mapping userIDs/objectIDs/accessdeviceIDs/serverIDs: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# Preparation for MOSS
# Create JSON contentblock with looped $filteredsi array
try {
$myArray = $filteredsi
$uniqueUsers = [System.Collections.ArrayList]::new()
for($i = 0; $i -lt $myArray.Count; $i++){
if(!$uniqueUsers.Contains($myArray[$i].userid)){
$uniqueUsers.Add($myArray[$i].userid)
}
}
$allMappings = [System.Collections.ArrayList]::new()
for($i = 0; $i -lt $uniqueUsers.Count; $i++){
$singleMapping = [PSCustomObject]@{id = $uniqueUsers[$i]; servers = $null}
$serverids = [System.Collections.ArrayList]::new()
for($j = 0; $j -lt $myArray.Count; $j++){
if($myArray[$j].userid -eq $uniqueUsers[$i]){
$serverids.Add($myArray[$j].serverid)
}
}
$singleMapping.servers = $serverids
$allMappings.Add($singleMapping)
}
$mosscontent = $allMappings | ConvertTo-Json
$mosscontent
}
catch {
$date+" - Error in creating content block for MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# Create complete array including contentblock for MOSS API call
try {
$moss = @"
{
"type": "server.usage",
"data": {
"users": $mosscontent
}
}
"@
}
catch {
$date+" - Error in creating array for POST to MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# 5. Call MOSS prod, dev and qa with the whole list of servers and users
# Authenticating to MOSS
$query_file_path_dev_pw = "~\Documents\MOSSDevEncryptedPassword_"
$query_file_path_qa_pw = "~\Documents\MOSSQaEncryptedPassword_"
$query_file_path_prod_pw = "~\Documents\MOSSProdEncryptedPassword_"
# Function to store credentials
function get_encrypted_content {
param (
[String] $file_path,
[String] $password
)
# Check if credentials file exis
if ( -Not (Test-Path -Path $file_path)) {
switch ($password) {
dev {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-dev-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
qa {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-qa-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
prod {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-prod-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
}
}
# Read credentials from file
$Encrypted_value = Get-Content -Path $file_path
# Decrypt credentials from file
return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))
}
# Define username and password
$clientid_dev = "mos-windows-us-dev"
$clientid_qa = "mos-windows-us-qa"
$clientid_prod = "mos-windows-us-prod"
$dev_pass = get_encrypted_content $query_file_path_dev_pw "dev"
$qa_pass = get_encrypted_content $query_file_path_qa_pw "qa"
$prod_pass = get_encrypted_content $query_file_path_prod_pw "prod"
[System.Security.SecureString]$clientsecret_dev = ConvertTo-SecureString -String $dev_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_qa = ConvertTo-SecureString -String $qa_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_prod = ConvertTo-SecureString -String $prod_pass -AsPlainText -Force
#Prepare static variables
$MOSSToken_dev = 'https://auth.00.idp.eu01.stackit.cloud/oauth/token'
$MOSSToken_qa = 'https://auth.01.idp.eu01.stackit.cloud/oauth/token'
$MOSSToken_prod = 'https://auth.01.idp.eu01.stackit.cloud/oauth/token'
$MOSSUrl_dev = "https://stackit-service-mos-dev.apps.01.cf.eu01.stackit.cloud/v1/events"
$MOSSUrl_qa = "https://stackit-service-mos-qa.apps.01.cf.eu01.stackit.cloud/v1/events"
$MOSSUrl_prod = "https://stackit-service-mos.apps.01.cf.eu01.stackit.cloud/v1/events"
$body = @{grant_type='client_credentials'}
#Set function to get all customerinfo from all portals
function call_moss {
param (
[String] $clientid,
[SecureString] $clientsecret,
[String] $MOSSToken,
[String] $MOSSUrl
)
$cred = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $clientid, $clientsecret
#Get Token from MOSS
$Response = Invoke-RestMethod -Uri $MOSSToken -Method Post -Credential $cred -Body $body -ContentType "application/x-www-form-urlencoded"
$Token = $Response.access_token
$Tokenfinal = "Bearer " + $Token
#Post Content to MOSS
Invoke-RestMethod -Uri $MOSSUrl -Method Post -Headers @{'Authorization' = $Tokenfinal } -Body $moss -ContentType "application/json"
}
#Call function to Call MOSS
try
{
Write-Host "Call to MOSS Dev.."
call_moss $clientid_dev $clientsecret_dev $MOSSToken_dev $MOSSUrl_dev
Write-Host "Call to MOSS QA.."
call_moss $clientid_qa $clientsecret_qa $MOSSToken_qa $MOSSUrl_qa
Write-Host "Call to MOSS Prod"
call_moss $clientid_prod $clientsecret_prod $MOSSToken_prod $MOSSUrl_prod
}
catch
{
$date+" - Error in calling MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
# 6. Create daily logs with users reported to MOSS
$date = $(get-date).tostring()
$log = foreach ($item in $filteredsi)
{
$item
}
echo $date $log | Out-file -Append $log_file_path
# delete logs older than 60 days
$limit = (Get-Date).AddDays(-60)
$path = "C:\Program Files\test\logs"
# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
# Create activity file to check if script is working
$temp_file_path = "C:\Program Files\test\tempfile*"
if (Test-Path $temp_file_path)
{
Remove-Item $temp_file_path
}
[string]$filePath = "C:\Program Files\test\tempfile";
[string]$directory = [System.IO.Path]::GetDirectoryName($filePath);
[string]$strippedFileName = [System.IO.Path]::GetFileNameWithoutExtension($filePath);
[string]$extension = [System.IO.Path]::GetExtension($filePath);
[string]$newFileName = $strippedFileName + "_" + (Get-Date).ToString('MM-dd-yyyy') + $extension;
[string]$newFilePath = [System.IO.Path]::Combine($directory, $newFileName);
New-Item $newFilePath
正在调用的其他脚本: -> request_database.ps1
# 1. Get path for log files
param(
[string]$log_file_path = "C:\Program Files\test\logs\request_database.log",
[string]$errorlog_file_path = "C:\Program Files\test\logs\request_database_errors.log"
)
# 2. Get credentials to access Octopus DB
try {
# Define username and password security string files
$mysql_user_file_path = "~\Documents\ue_"
$mysql_pass_file_path = "~\Documents\pe_"
# Functions
function get_encrypted_content {
param (
[String] $file_path,
[String] $user_or_pass
)
# Check if credentials file exist
if ( -Not (Test-Path -Path $file_path)) {
switch ($user_or_pass) {
msqu {
# Get credentials
Read-Host -Prompt "Please, enter MySQL username" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
msqp {
# Get credentials
Read-Host -Prompt "Please, enter MySQL password" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
}
}
# Read credentials from file
$Encrypted_value = Get-Content -Path $file_path
# Decrypt credentials from file
return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))
}
# Define username and password
$my_sql_user = get_encrypted_content $mysql_user_file_path "msqu"
$my_sql_pass = get_encrypted_content $mysql_pass_file_path "msqp"
[System.Security.SecureString]$SecPwd = ConvertTo-SecureString -String $my_sql_pass -AsPlainText -Force
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist @($my_sql_user,$SecPwd)
}
catch {
$(get-date).tostring() +" - Error in fetching SQL user/pwd: "+$_ | Out-File -Append $errorlog_file_path
exit
}
$error_string = ""
# 3. Execute DB query
# If you want the script to continue on error you have to provide $true as second parameter
# Example: execute_db_query $exclude_stackitadmin_users_query $true
function execute_db_query {
param (
[String] $query,
[bool] $continueOnError = $false
)
try {
# Query Octopus DB
Connect-MySqlServer -Credential $Credential -Server localhost
if ($continueOnError) {
$query_results = Invoke-MySqlQuery -Query $query
} else {
$query_results = Invoke-MySqlQuery -Query $query -ErrorAction Stop
}
Disconnect-MySqlServer
return $query_results
}
catch {
$error_message = $(get-date).tostring() + " - Error in DB Query 1: " + $_
$error_message | Out-File -Append $errorlog_file_path
Write-Error $error_message
exit
}
}
-> exclude_users.ps1(任务可能不需要,但没有它整个脚本将无法运行)
# 1. Get path for log files or use default
param(
[string]$log_file_path = "C:\Program Files\test\logs\exclude_users.log",
[string]$errorlog_file_path = "C:\Program Files\test\logs\errors\exclude_users_errors.log"
)
Import-Module -Name "C:\Program Files\test\request_database.ps1" -ArgumentList $log_file_path, $errorlog_file_path -Verbose
# Exclude StackitAdmin users
$exclude_stackitadmin_users_query =
@"
update oc_reporter.ws_user as updated_user,
(
select id from oc_reporter.ws_user
where username = "StackITAdmin" and exclude_spla = "no"
) as us
set
exclude_spla = "yes",
exclude_spla_reason = "nh"
where updated_user.id = us.id;
"@
execute_db_query($exclude_stackitadmin_users_query)
# Exclude users on dev & qa environment
$exclude_users_on_dev_qa_query =
@"
update oc_reporter.ws_installed_software as updated_software,
(
select ws.access_device_ids, min(ws.access_device_labels), min(ws.user_label), excluded_users, min(ws.id) as id from oc_reporter.ws_user
join oc_reporter.ws_installed_software as ws
on ws.user_id = ws_user.id
join oc_reporter.ws_customer as wc
on wc.id = ws_user.customer_id
left join
(select access_device_ids, count(1) as excluded_users from oc_reporter.ws_user as wu
join oc_reporter.ws_customer as wc
on wc.id = wu.customer_id
join oc_reporter.ws_installed_software as ws
on ws.user_id = wu.id
where
(internal_id like "d-%" or internal_id like "q-%") and
locate(',', access_device_ids) = 0 and
ws.exclude_spla = "yes" and
ws.label = "Microsoft Remote Desktop Services" and
wu.username != "StackitAdmin"
group by access_device_ids, wu.exclude_spla) as servers
on servers.access_device_ids = ws.access_device_ids
where
ws.exclude_spla = "no" and
ws.label = "Microsoft Remote Desktop Services" and
(internal_id like "d-%" or internal_id like "q-%") and
locate(',', ws.access_device_ids) = 0
group by ws.access_device_ids
having (excluded_users = 1 or excluded_users is null)
) as us
set
exclude_spla = "yes",
exclude_spla_reason = "admin"
where updated_software.id = us.id;
"@
# run twice to exlude 2 users per vm
execute_db_query($exclude_users_on_dev_qa_query)
execute_db_query($exclude_users_on_dev_qa_query)
# Exclude users from our mos-windows-2 project
$exclude_users_from_our_projects =
@"
update oc_reporter.ws_installed_software as ins,
(
select ws.access_device_ids, min(ws.access_device_labels), min(ws.user_label), excluded_users, min(ws.id) as id, min(wu.id) from oc_reporter.ws_user as wu
join oc_reporter.ws_installed_software as ws
on ws.user_id = wu.id
join oc_reporter.ws_device as wd
on wd.id = ws.access_device_ids
left join (
select ws.access_device_ids, min(ws.id), min(wu.id), count(1) as excluded_users from oc_reporter.ws_user as wu
join oc_reporter.ws_installed_software as ws
on ws.user_id = wu.id
join oc_reporter.ws_device as wd
on wd.id = ws.access_device_ids
where
ws.exclude_spla = "yes" and
ws.label = "Microsoft Remote Desktop Services" and
LOCATE(',',access_device_ids) = 0 and
(
hkey like "%d57abb0200304506879bd8037f7a49cb%" or
hkey like "%fce60e2c938c49e4a37687492a45b652%" or
hkey like "%8eb91d45f25b45978b71abb0e06a0443%" or
hkey like "%66ad75e4ff624f7e940dc363549c8404%" or
hkey like "%351aa84fb9b54be896112b36ae15dd48%" or
hkey like "%64edd6c19e17417d86094e6a02610eed%"
) and
wu.username != "StackitAdmin"
group by ws.access_device_ids
) as excluded_ws
on
excluded_ws.access_device_ids = ws.access_device_ids
where
ws.exclude_spla = "no" and
ws.label = "Microsoft Remote Desktop Services" and
LOCATE(',',ws.access_device_ids) = 0 and
(
hkey like "%d57abb0200304506879bd8037f7a49cb%" or
hkey like "%fce60e2c938c49e4a37687492a45b652%" or
hkey like "%8eb91d45f25b45978b71abb0e06a0443%" or
hkey like "%66ad75e4ff624f7e940dc363549c8404%" or
hkey like "%351aa84fb9b54be896112b36ae15dd48%" or
hkey like "%64edd6c19e17417d86094e6a02610eed%"
) and
wu.domain not like "%HOP01%" and
wu.domain not like "%WSUS01%" and
wu.domain not like "%OCKMS%" and
wu.domain not like "%AZDVOP%"
group by ws.access_device_ids
having (excluded_users = 1 or excluded_users is null)
) as rds
set
exclude_spla = "yes",
exclude_spla_reason = "admin"
where ins.id = rds.id;
"@
# run twice to exlude 2 users per vm
execute_db_query($exclude_users_from_our_projects)
execute_db_query($exclude_users_from_our_projects)
顺序错误,还有很多不必要的元素导致错误和崩溃。
当前的工作代码是:
# Compare the data between the MOSS and the Octopus
# Define log file path
$date = $(get-date).tostring()
$currentdate = get-date -format yyyy-MM-dd
$log_file_path = "[FILE PATH]"
$errorlog_file_path = "[FILE PATH]"
# 1. Call MOSS (dev, qa, prod) to get the data for all servers created in the last 48 hours
# Authenticating to MOSS
$query_file_path_dev_pw = "[FILE PATH]"
$query_file_path_qa_pw = "[FILE PATH]"
$query_file_path_prod_pw = "[FILE PATH]"
# Function to store credentials
function get_encrypted_content {
param (
[String] $file_path,
[String] $password
)
# Check if credentials file exis
if ( -Not (Test-Path -Path $file_path)) {
switch ($password) {
dev {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-dev-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
qa {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-qa-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
prod {
# Get credentials
Read-Host -Prompt "Enter password for mos-windows-us-prod-client-id" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath $file_path
}
}
}
# Read credentials from file
$Encrypted_value = Get-Content -Path $file_path
# Decrypt credentials from file
return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString $Encrypted_value)))
}
# Define username and password
$clientid_dev = "[USERNAME]"
$clientid_qa = "[USERNAME]"
$clientid_prod = "[USERNAME]"
$dev_pass = get_encrypted_content $query_file_path_dev_pw "dev"
$qa_pass = get_encrypted_content $query_file_path_qa_pw "qa"
$prod_pass = get_encrypted_content $query_file_path_prod_pw "prod"
[System.Security.SecureString]$clientsecret_dev = ConvertTo-SecureString -String $dev_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_qa = ConvertTo-SecureString -String $qa_pass -AsPlainText -Force
[System.Security.SecureString]$clientsecret_prod = ConvertTo-SecureString -String $prod_pass -AsPlainText -Force
# Time variable
$date48h = ("{0:yyyy-MM-ddThh:mm:ss}" -f ((get-date).Addhours(-48))).split("T").split(":")
$date = $date48h[0]
$hour = $date48h[1]
$min = $date48h[2]
$sec = $date48h[3]
#Prepare static variables
$MOSSToken_dev = '[URL]'
$MOSSToken_qa = '[URL]'
$MOSSToken_prod = '[URL]'
$MOSSUrl_dev = "[URL]"
$MOSSUrl_qa = "[URL]"
$MOSSUrl_prod = "[URL]"
$body = @{grant_type='client_credentials'}
#Set function to get all customerinfo from all portals
function call_moss {
param (
[String] $clientid,
[SecureString] $clientsecret,
[String] $MOSSToken,
[String] $MOSSUrl
)
$cred = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $clientid, $clientsecret
#Get Token from MOSS
$Response = Invoke-RestMethod -Uri $MOSSToken -Method Post -Credential $cred -Body $body -ContentType "application/x-www-form-urlencoded"
$Token = $Response.access_token
$Tokenfinal = "Bearer " + $Token
#Post Content to MOSS
Invoke-RestMethod -Uri $MOSSUrl -Method Get -Headers @{'Authorization' = $Tokenfinal } -ContentType "application/json"
}
#Call function to Call MOSS
try
{
Write-Host "Call to MOSS Dev.."
$get_moss_dev = call_moss $clientid_dev $clientsecret_dev $MOSSToken_dev $MOSSUrl_dev
Write-Host "Call to MOSS QA.."
$get_moss_qa = call_moss $clientid_qa $clientsecret_qa $MOSSToken_qa $MOSSUrl_qa
Write-Host "Call to MOSS Prod"
$get_moss_prod = call_moss $clientid_prod $clientsecret_prod $MOSSToken_prod $MOSSUrl_prod
}
catch
{
$date+" - Error in calling MOSS: "+$_ | Out-File -Append $errorlog_file_path
exit
}
$moss_dev_serverids = $get_moss_dev.items.id
$moss_qa_serverids = $get_moss_qa.items.id
$moss_prod_serverids = $get_moss_prod.items.id
$moss_serverid_arr = @($moss_dev_serverids, $moss_qa_serverids, $moss_prod_serverids)
# 2. Call Octopus to get the data for new servers created in the last 36 hours
Import-Module -Name "[FILE PATH]" -ArgumentList $log_file_path, $errorlog_file_path -Verbose
# Calculate timestamp
$DateTime = Get-Date #or any other command to get DateTime object
$CurrentUnixTime = ([DateTimeOffset]$DateTime).ToUnixTimeSeconds()
$queryTime = $CurrentUnixTime - (36 * 3600)
$get_new_servers_query_oc =
@"
select id, lower(SUBSTRING_INDEX(SUBSTRING_INDEX(ref_id, "-", -6), "-", 5)) as server_id, ref_id, label from oc_reporter.ws_device where type_id = "vm" and operating_system like "%Windows%" and created > $queryTime;
"@
$query = execute_db_query $get_new_servers_query_oc
$serverid_oc = $query.server_id
$serverid_oc_arr = @($serverid_oc)
# 3. Compare the properties in MOSS and Octopus
$unmatching_serverids = $serverid_oc_arr | Where {$moss_serverid_arr -NotContains $_}
$error_report = @($unmatching_serverids)
# Create daily logs with servers in Octopus that are unregistered in MOSS
$date = $(get-date).tostring()
$log = $error_report
echo $date $log | Out-file -Append $log_file_path
# delete logs older than 60 days
$limit = (Get-Date).AddDays(-60)
$path = "[FILE PATH]"
# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
# 4. Generate summary with all errors and send a notification if there is an error. Schedule a task to check once per day.
If ($error_report.Count -eq 0) {
exit
}
else {
$JSONBody = [PSCustomObject][Ordered] @{
"type" = "MessageCard"
"title" = "Octopus Alerts"
"text" = "Servers located in Octopus, that are not registered in MOSS. <br>
Please check logs."
}
$TeamsMessageBody = ConvertTo-Json $JSONBody
$parameters = @{
"URI" = '[URL]'
"Method" = 'POST'
"Body" = $TeamsMessageBody
"ContentType" = 'application/json'
}
Invoke-RestMethod @parameters
}
# Create activity file to check if script is working
$temp_file_path = "[FILE PATH]"
if (Test-Path $temp_file_path)
{
Remove-Item $temp_file_path
}
[string]$filePath = "[FILE PATH]";
[string]$directory = [System.IO.Path]::GetDirectoryName($filePath);
[string]$strippedFileName = [System.IO.Path]::GetFileNameWithoutExtension($filePath);
[string]$extension = [System.IO.Path]::GetExtension($filePath);
[string]$newFileName = $strippedFileName + "_" + (Get-Date).ToString('MM-dd-yyyy') + $extension;
[string]$newFilePath = [System.IO.Path]::Combine($directory, $newFileName);
New-Item $newFilePath
此外,如前所述,完全不需要 exclude_users 脚本。唯一额外包含的脚本是 request_database 脚本。