Skip to content

Commit

Permalink
Updates to WazuhAgentRegister resource
Browse files Browse the repository at this point in the history
  • Loading branch information
Unknown committed Oct 25, 2017
1 parent 5982955 commit 2731ee6
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 53 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
// When enabled, will trim trailing whitespace when you save a file.
"files.trimTrailingWhitespace": true
"files.trimTrailingWhitespace": true,
"editor.formatOnSave": false,
"powershell.codeFormatting.preset": "Allman"
}
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# WazuhOSSec
# WazuhOSSecDSC
Powershell DSC Class based resource for installing and configuring the Wazuh Agent

The **WazuhOSSec** DSC resources allow you to install and register the Wazuh Ossec Agent with the defined Wazuh Server.
The **WazuhOSSecDSC** resources allow you to install and register the Wazuh Ossec Agent with the defined Wazuh Server.


## Description
The **WazuhOSSec** DSC module contains the **WazuhAgentInstall** and **WazuhAgentRegister** DSC Resources. These resources were built using PowerShell Classes and such will require Powershell 5.0 +. These DSC resources allow you to install the Wazuh agent and regster it with the Wazuh server.
The **WazuhOSSecDSC** module contains the **WazuhAgentInstall** and **WazuhAgentRegister** DSC Resources. These resources were built using PowerShell Classes and as such will require Powershell 5.0+. These DSC resources allow you to install the Wazuh agent and register it with the Wazuh server.

## Resources
* **WazuhAgentInstall** Installs or Upgrades the Wazuh Agent from a path you provide.
* **WazuhAgentRegister** Registers an agent with the Wazuh server
* **WazuhAgentRegister** Registers or Deletes an agent on the Wazuh Manager.

### **WazuhAgentInstall**
* **InstallerPath** - Path to the Wazuh Agent installer on the local server.
* **Ensure** - Install or uninstall the agent. (Present/Absent)
* **Ensure** - Install or uninstall the agent. (Present/Absent).

### **WazuhAgentRegister**
* **AgentName** - The name you want to register for the Agent.
Expand All @@ -22,7 +22,7 @@ The **WazuhOSSec** DSC module contains the **WazuhAgentInstall** and **WazuhAgen
* **UseSelfSignedCerts** - Determines whether to use a self signed cert with the Wazuh server. Default is false.
* **ApiPollingInterval** - Used to determine a polling interval for checking if the agent is registered. Default is 0 for no interval meaning the resource will poll the server everytime DSC is run. Specified in minutes.
* **Credential** - PSCredential object passed into the rersource for authenticating to the Wazuh server
* **Ensure** - Register the agent with the wazuh server. (Present/Absent)
* **Ensure** - Registers or Deletes the agent on the Wazuh Manager. (Present/Absent)

## Versions

Expand Down
8 changes: 4 additions & 4 deletions WazuhOSSec.psd1 → WazuhOSSecDSC.psd1
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#
# Module manifest for module 'MyModule'
# Module manifest for module 'WazuhOSSecDSC'
#
# Generated by: Marco
# Generated by: Marco Crank
#
# Generated on: 10/4/2017
#

@{

# Script module or binary module file associated with this manifest.
RootModule = 'WazuhOSSec.psm1'
RootModule = 'WazuhOSSecDSC.psm1'

# Version number of this module.
ModuleVersion = '1.0.0'
Expand Down Expand Up @@ -101,7 +101,7 @@
# LicenseUri = ''

# A URL to the main website for this project.
ProjectUri = 'https://github.com/LeanKit-Labs/WazuhOSSec'
ProjectUri = 'https://github.com/LeanKit-Labs/WazuhOSSecDSC'

# A URL to an icon representing this module.
# IconUri = ''
Expand Down
191 changes: 149 additions & 42 deletions WazuhOSSec.psm1 → WazuhOSSecDSC.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,15 @@ class WazuhAgentRegister
[DscProperty(NotConfigurable)]
[bool]$AgentRegistered

[DscProperty(NotConfigurable)]
[bool]$AgentRegisterExisting

[DscProperty(NotConfigurable)]
[AgentStatus]$AgentStatus

[DscProperty(NotConfigurable)]
[string]$AgentIDFromAPI

[WazuhAgentRegister] Get()
{
#Set Certificate policy to ignore Self Signed Certs, False by default.
Expand All @@ -205,65 +211,102 @@ class WazuhAgentRegister
Write-Verbose "Allowing Self Signed Certs"
$this.IgnoreSelfSignedCerts()
}
Write-Verbose "Agent Name: $($this.AgentName)"
$this.BaseUrl = "https://" + $this.WazuhServerApiFqdn + ":" + $this.WazuhServerApiPort
Write-Verbose "Base URL: $($this.BaseUrl)"
$this.AgentPath = $this.GetAgentPath()
Write-Verbose "Agent Path: $($This.AgentPath)"
$this.AgentConfigFile = $this.AgentPath + "\" + $this.AgentConfigFile
Write-Verbose "OSSec Agent Config: $($This.AgentConfigFile)"
$this.WazuhServerApiIP = $this.GetWazuhServeIP()
Write-Verbose "Wazuh Server IP: $($This.WazuhServerApiIP)"

# This block uses the ApiPollingInterval value to determine if it should poll for Agent Registration.
# We put this in to alleviate unnecessary API calls to the server. Other wise every time DSC ran this would make a call
# to the API to verify the Agent was registered. Most of which would return back $true.
# If no ApiPollingInterval is set it wll poll each time
if (($this.ApiPollingInterval -eq 0) -or (($this.InitializePolling()) -and ($this.ApiPollingInterval -ne 0)))
{
#If PollingInterval is 0 cleanup the polling file so we don't have any lingering data lying around should the interval change later
if (($this.ApiPollingInterval -eq 0) -and (Test-Path ($this.AgentPath + "\DSC_Polling.log") -PathType Leaf))

if ($this.Ensure -eq [Ensure]::Present)
{
$this.AgentPath = $this.GetAgentPath()
$this.AgentConfigFile = $this.AgentPath + "\" + $this.AgentConfigFile
$this.WazuhServerApiIP = $this.GetWazuhServeIP()
Write-Verbose "Agent Name: $($this.AgentName)"
Write-Verbose "Base URL: $($this.BaseUrl)"
Write-Verbose "Agent Path: $($This.AgentPath)"
Write-Verbose "OSSec Agent Config: $($This.AgentConfigFile)"
Write-Verbose "Wazuh Server IP: $($This.WazuhServerApiIP)"

# This block uses the ApiPollingInterval value to determine if it should poll for Agent Registration.
# We put this in to alleviate unnecessary API calls to the server. Other wise every time DSC ran this would make a call
# to the API to verify the Agent was registered. Most of which would return back $true.
# If no ApiPollingInterval is set it wll poll each time
if (($this.ApiPollingInterval -eq 0) -or (($this.InitializePolling()) -and ($this.ApiPollingInterval -ne 0)))
{
#If PollingInterval is 0 cleanup the polling file so we don't have any lingering data lying around should the interval change later
if (($this.ApiPollingInterval -eq 0) -and (Test-Path ($this.AgentPath + "\DSC_Polling.log") -PathType Leaf))
{
Write-Verbose "ApiPollingInterval set to 0, Cleaning up Polling Log File"
Remove-Item -Path ($this.AgentPath + "\DSC_Polling.log") -Force
}
$_RegistrationStatus = $this.RegistrationStatus()
$this.AgentRegistered = $_RegistrationStatus.AgentRegistered
$this.AgentRegisterExisting = $_RegistrationStatus.AgentRegisterExisting
}
else
{
Remove-Item -Path ($this.AgentPath + "\DSC_Polling.log") -Force
#No need to poll for agent status so assume Registered with the server
$this.AgentRegistered = $true
}
$AgentPollResult = $this.GetAgentInfo()
return $this
}
else
{
$_AgentMetaData = $this.GetAgentInfo() | ConvertFrom-Json
#If Total Items greater than or equal to 1 the agent should be registered
if (($agentPollResult | ConvertFrom-Json).data.totalitems -ge 1)
if (($_AgentMetaData).data.totalitems -ge 1)
{
$this.AgentRegistered = $true
}
else
{
$this.AgentRegistered = $false
}
return $this
}
else
{
#No need to poll for agent status so assume Registered with the server
$this.AgentRegistered = $true
}
return $this
}

[bool] Test()
{
$this.Get()
if (!($this.AgentRegistered))
$_Get = $this.Get()
if ($this.Ensure -eq [Ensure]::Present)
{
if ($_Get.AgentRegistered)
{
Write-Verbose "Agent is registered. GOOD JOB!"
return $true
}
Write-Verbose "Agent is not registered, Begin registration process."
return $false
}
else # Ensure = Absent
{
Write-Verbose "Ensure set to `"Absent`", Checking for existing Agent."
if (!($_Get.AgentRegistered))
{
Write-Verbose "No Agent found on server."
return $true
}
Write-Verbose "Agent found on server, begin deletion process."
return $false
}
return $true
}

[void] Set()
{
# Register the Agent, Get the Key from Wazuh Server, Import the Key, update ossec.conf, and restart the Agent service
$AgentRegisterResponse = $this.AgentRegisterNew()
$AgentKeyResponse = $this.GetAgentKey($AgentRegisterResponse)
$this.ImportAgentKey($AgentKeyResponse)
$this.AgentControl([AgentStatus]::Stop)
$this.UpdateConfigFile()
$this.AgentControl([AgentStatus]::Start)
$_Get = $this.RegistrationStatus()

if ($_Get.AgentRegisterExisting -or ($this.Ensure -eq [Ensure]::Absent))
{
# If there is an existing Agent, Deleted the old and Re-Register as a new agent
$this.AgentRegisterDelete($this.AgentIDFromAPI)
}
if ($this.Ensure -eq [Ensure]::Present)
{
$_AgentRegisterResponseId = $this.AgentRegisterNew()
$_AgentKeyResponse = $this.GetAgentKey($_AgentRegisterResponseId)
$this.ImportAgentKey($_AgentKeyResponse)
$this.AgentControl([AgentStatus]::Stop)
$this.UpdateConfigFile()
$this.AgentControl([AgentStatus]::Start)
}
}

#region Helper Methods
Expand All @@ -284,12 +327,26 @@ class WazuhAgentRegister
}
}

[string]AgentRegisterDelete($AgentId)
{
Write-Verbose "Deleting Agent from server: $($This.AgentName)"
$ApiResponse = $this.WazuhApiRequest("DELETE", "/agents/$($AgentId)") | ConvertFrom-Json
If ($ApiResponse.error -ne '0')
{
throw "ERROR: $($ApiResponse.message)"
}
else
{
Write-Verbose "Agent Deleted: (Agent - $($this.AgentName)) / (ID - $($AgentId))"
return $AgentId
}
}

[string] GetAgentKey($AgentId)
{
# Getting agent key from manager
# Small sleep, experienced a timing issue after registering
Start-Sleep -Seconds 2
Write-Verbose "Retrieving Agent Key from server"
#$response = req -method "GET" -resource "/agents/$($agent_id)/key" | ConvertFrom-Json
#ToDo: I think converFrom-Json on the call lilke above so we don't have to below.
$_ApiResponse = $this.WazuhApiRequest("Get", "/agents/$($AgentId)/key") | ConvertFrom-Json
If ($_ApiResponse.error -ne '0')
{
Expand All @@ -309,8 +366,9 @@ class WazuhAgentRegister
Write-Output "y" | & "$($this.GetAgentPath())\manage_agents.exe" "-i $($AgentKey)" "y`r`n"
}

# If UseSelfSignedCerts=$true modify Certificate Policy to allow

[void]IgnoreSelfSignedCerts()
# If UseSelfSignedCerts=$true modify Certificate Policy to allow
{
add-type @"
using System.Net;
Expand Down Expand Up @@ -492,7 +550,6 @@ class WazuhAgentRegister
}
}

#The following two methods are used in various other methods so we broke them out to reduce code and make it simpler...we hope.
[string]GetWazuhServeIP()
{
Write-Verbose "Resolving Wazuh Server IP Address"
Expand All @@ -508,8 +565,9 @@ class WazuhAgentRegister

[string]GetAgentPath()
{
if ($_AgentPath = (Get-Package -Name "*wazuh*").Meta.Attributes.Get_Item("UninstallString").trim([char]"`"") | Split-Path )
if ($_AgentPath = (Get-Package -Name "*wazuh*" -ErrorAction SilentlyContinue))
{
$_AgentPath = $_AgentPath.Meta.Attributes.Get_Item("UninstallString").trim([char]"`"") | Split-Path
return $_AgentPath
}
else
Expand All @@ -518,5 +576,54 @@ class WazuhAgentRegister
}
}

[hashtable]RegistrationStatus()
{
$_RegistrationStatus = [Hashtable]::new()
$_AgentMetaData = $this.GetAgentInfo() | ConvertFrom-Json
#If Total Items greater than or equal to 1 the agent should be registered
if (($_AgentMetaData).data.totalitems -ge 1)
{
Write-Verbose "Existing Agent found"
# Setting this value here so we can use it in the Set() Method to pull back Keys
$this.AgentIDFromAPI = $_AgentMetaData.data.items.id
#We need Path to Client.keys File C:|Program FIles (x86)\Ossec-agent
if (Test-Path ($this.AgentPath + "\Client.keys"))
{
Write-Verbose "Existing Client.Keys file found"
$_clientKeyFilePath = $this.AgentPath + "\Client.keys"
$_currentID = ((Get-Content -Path $_clientKeyFilePath).Split(' '))[0]
$_currentStatus = ($_AgentMetaData).data.items.status
if ((($this.AgentIDFromAPI) -eq $_currentID) -and ($_currentStatus) -ne "Never connected" )
{
Write-Verbose "Current Agent ID matches Manager Agent ID and Status is Active or Disconnected - Assuming Agent Registered"
#Total Items ge 1, There is a CLient.keys file, the Agent ID from API and Client.keys match, and the agent status is disconnected or active
$_RegistrationStatus.add('AgentRegistered', $true)
}
else
{
Write-Verbose "Client.Keys file exists but Agent IDs do not match or Status is `"Never Connected`""
# Total Items ge 1, there is a CLient.keys file, and Status is "Never Connected"
# Use the "Insert" API to re-use the Agent ID
$_RegistrationStatus.add('AgentRegistered', $false)
$_RegistrationStatus.add('AgentRegisterExisting', $true)
}
}
else
{
Write-Verbose "No Client.Keys file exists, assuming not registered"
#Total Items ge 1, There is no CLient.keys file
# Use the "Insert" API to re-use the Agent ID
$_RegistrationStatus.add('AgentRegistered', $false)
$_RegistrationStatus.add('AgentRegisterExisting', $true)
}
}
else
{
Write-Verbose "No Agent found on Manager, Agent not registered"
$_RegistrationStatus.add('AgentRegistered', $false)
}
Return $_RegistrationStatus
}

#endregion
}

0 comments on commit 2731ee6

Please sign in to comment.