FOG API AD JSON Settings



  • Hi all,

    I’ve created a PowerShell module for managing our FOG server, and I’m currently having difficulty getting the AD settings to work as expected. I currently have the following when adding a new FOG computer:

    $HostJson = @{
                "name"=  $MachineName
                "macs" =  @($MacAddress)
                "imageID"= $Image.id
                "imagename" =  $ImageName
                "useAD" = $UseAD
                "ADDomain" = $ADDomain
                "ADUser" = $ADUser
    	    "ADPass" = $FOGPWD
                "enforce" = $Enforce
    }
    Try{                    
        $CreateHostJson = ConvertTo-Json($HostJson)
        $CreateHostURL = $BaseUri +"/host/create"
        $CreateHostResult = Invoke-RestMethod -Uri $CreateHostURL -Method POST -body $CreateHostJson -Headers $Headers -ContentType "application/json"
    }
    Catch{
    Write-Error $_.Exception.Message
    Break
    }
    

    However, when checking the FOG client AD settings, I see everything is left unchecked, and the FOG log shows:

    Service Creating user agent cache
    Middleware::Response Invalid time
    Middleware::Response No Printers
    Middleware::Response Module is disabled globally on the FOG server
    Service Initializing modules
    

    It is only after removing the host manually and running the PowerShell command again (and then rebooting the system) that FOG finally recognises it, but the AD settings still aren’t displayed unless I check the ‘Join Domain After Deploy’ checkbox.
    Is there a way to set that through the FOG API, and have the default settings for the domain join filled out? This would also save users of this module having to find and copy/paste the admin password for joining the domain.

    Any help with this would be greatly appreciated!


  • Testers

    @RobTitian16

    I realize this is a few month’s old. But you might want to check out and or contribute to the fog module I have in git and published in the powershellgallery, there’s a forum post with more info here https://forums.fogproject.org/post/120746
    Also did you have a chance to try the code I posted back in september and see if that worked? Because it works for me.
    And looking again at your code I would ask what the value of $useAD is, is it 1 it should be 1. And I would also try piping the object into convertto-json, I’ve had better luck with that, I think it parses it different i.e. $CreateHostJson = $HostJson | ConvertTo-Json I would also encapsulate everything in quotes on the splat.
    The only other thing that might be an issue is the ADPass. When you get the password via the api it is returned in plain text (because you already authenticated with api keys, so it’s not like just anyone can grab it). When you input the password in the gui you put it in plaintext and it encrypts when you hit save, I don’t think the same thing happens if you set it through the api. My solution has been to always enable the default AD settings when adding a host via the gui or the pxe menu. But it sounds like you’re adding the host through the api. The “useAD”=“1” in the json should be causing the checkbox for the ‘join domain after deploy’ to be checked. Sadly when you check it from the api it doesn’t pull the default domain settings. You might try creating the host without the AD settings and then sending just the AD settings in an update/put command. If you copy paste the already encrypted password from a working host in the gui, that might do the trick as it seems to pass whatever you put in that field to be in plaintext.

    So point is, try adding the domain stuff with an update api command after creating. And use the code I have in the example to help if needed.


  • Testers

    @mparlette Why thank you good sir =)
    I keep meaning to update some pieces of that module but keep not having time.

    But anyway, I have been using the api via powershell for AD stuff since I made it

    I don’t have time to delve deep into an explanation right now but here’s a quick code example that I use to create an OU string based on the fog group name and then add the domain join info. It doesn’t all use my api as it and could use some optimization but it works as it is so I haven’t updated it yet. But the invoke-fogapi command I believe is the same as in the module published in the powershell gallery. So it can work together.

    Though another quick note, it looks like the OP’s error message is saying AD is disabled on the server. Make sure that it isn’t actually disabled. YOu can also try resetting the encryption data on the client.

    function Set-FogOU {
        [CmdletBinding()]
        param (
            [string]$jsonData,
            $hostObj,
            [string]$OUstr
        )
    
        begin {
            if($null -eq $hostObj) {
                Write-Verbose 'no host given, getting current host...';
                $hostObj = Get-FogHost
            }
            Write-Verbose 'getting fog group...';
    
            $group = Get-FogGroup $hostObj.id;
    
    
            if ($group.name -match 'wks' -OR $group.name -match 'TS') {
                if ($null -eq $OUstr -OR $OUstr -eq "") {
                    Write-Verbose 'checking if group is domain group'
                    $OUstr = Get-OUStr -group $group;
                }
                Write-Verbose "OU string is $OUstr, setting to properties of host object, also enabling and enforcing domain join...";
                $hostObj.ADOU = $OUstr;
                $hostObj.useAD = 1;
                $hostObj.enforce = 1;
            }
            else { #group name doesn't have wks in it so don't join the domain
                Write-Verbose "Group name $($group.name) is not a domain group, setting fog to not join the domain, but still restart to name the computer...";
                $hostObj.ADOU = "";
                $hostObj.useAD = 0;
                $hostObj.enforce = 1;
            }
    
            Write-Verbose 'creating json string from new host ou settings...';
            $jsonData = $hostObj | Select-Object id,ADOU,useAD,enforce | ConvertTo-Json;
        }
    
        process {
            Write-Verbose "Setting $($hostObj.name)'s OU settings to $jsonData";
            $newHost = Invoke-FogApi -Method 'Put' -uriPath "host/$($hostObj.id)/edit" -jsonData $jsonData;
        }
    
        end {
            Write-Verbose "OU and AD settings have been set for $($newHost.name)";
            Write-Verbose 'host settings are now...';
            $newHost | Select-Object id,name,ADOU,useAD,enforce
            return;
        }
    }
    
    function Get-OUStr {
        [CmdletBinding()]
        param (
            $group,
            $OUstr = ''
        )
    
        begin {
            # $OUstr = "";
            Write-Verbose "getting OUstring for group $($group.name)";
        }
    
        process {
            if ($group.name -match 'wks' -OR $group.name -match 'TS') {
                Write-Verbose 'group should be in an OU, creating OU string from group name or using given string...';
                if ($null -ne $OUstr -AND $OUstr -ne "") {
                    Write-Verbose 'using given ouString'
                    $OUstr = $OUstr;
                }
    
                else {
                    Write-Verbose 'creating wks ou string';
                    $OUstr = "OU=$($group.name),OU=Desktop,OU=Workstations,DC=domain,DC=com";
                }
                Write-Verbose "OU string is $OUstr, setting to properties of host object, also enabling and enforcing domain join...";
            }
        }
    
        end {
            return $OUstr;
        }
    }
    
    function Get-FogHost {
        [CmdletBinding()]
        param (
            [string]$uuid,
            [string]$hostName,
            [string]$macAddr
        )
    
        begin {
            [bool]$found = $false;
            Write-Verbose 'Checking for passed variables'
            if (!$uuid -and !$hostName -and !$macAddr) {
                Write-Verbose 'no params given, getting current computer variables';
                $uuid = (Get-WmiObject Win32_ComputerSystemProduct).UUID;
                $macAddr = ((Get-NetAdapter | Select-Object MacAddress)[0].MacAddress).Replace('-',':');
                $hostName = $(hostname);
            }
            Write-Verbose 'getting all hosts to search...';
            $hosts = (Invoke-FogApi).hosts;
            Write-Verbose "search terms: uuid is $uuid, macAddr is $macAddr, hostname is $hostName";
        }
    
        process {
            Write-Verbose 'finding host in hosts';
            [bool]$found = $false;
            $hostObj = $hosts | Where-Object {
                ($uuid -ne "" -AND $_.inventory.sysuuid -eq $uuid) -OR `
                ($hostName -ne "" -AND $_.name -eq $hostName) -OR `
                ($macAddr -ne "" -AND $_.macs -contains $macAddr);
                if  ($uuid -ne "" -AND $_.inventory.sysuuid -eq $uuid) {
                     Write-Verbose "$($_.inventory.sysuuid) matches the uuid $uuid`! host found";
                     $found = $true;
                }
                if ($macAddr -ne "" -AND $_.macs -contains $macAddr) {
                    Write-Verbose "$($_.macs) matches the macaddress $macAddr`! host found";
                    $found = $true;
                }
                if  ($hostName -ne "" -AND $_.name -eq $hostName) {
                    Write-Verbose "$($_.name) matches the hostname $hostName`! host found";
                    $found = $true;
                }
            }
    
        }
    
        end {
            if ($found){
                return $hostObj;
            }
            return $found; #return false if host not found
        }
    }
    
    function Get-FogGroup {
        <#
        .SYNOPSIS
        needs to return the group name of the group that isn't the everyone group
        will use groupassociation call to get group id then group id to get group name from group uriPath
    
        .DESCRIPTION
        requires the id of the host you want the groups that aren't the everyone group for
        #>
        [CmdletBinding()]
        param (
            [int]$hostId
        )
    
        begin {
            [bool]$found = $false;
            Write-Verbose 'Getting all fog group associations...';
            $groupAssocs = (Invoke-FogApi -uriPath groupassociation).groupassociations;
            Write-Verbose 'Getting all fog groups...';
            $groups = (Invoke-FogApi -uriPath group).groups;
        }
    
        process {
            Write-Verbose "Finding group association for hostid of $hostId";
            $hostGroups = $groupAssocs | Where-Object hostID -eq $hostId;
            Write-Verbose "filtering out everyone and touchscreen group";
            $hostGroups = $hostGroups | Where-Object groupID -ne 3; #groupID 3 is the everyone group, don't include that
            $hostGroups = $hostGroups | Where-Object groupID -ne 11; #groupID 11 is the wkstouchscreens group, don't include that either
    
            Write-Verbose "finding group that matches group id of $hostGroups...";
            $group = $groups | Where-Object id -eq $hostGroups.groupID;
            Write-Verbose 'checking if group was found...';
            if($null -ne $group -AND $group -ne "") { $found = $true; Write-Verbose 'group found!'}
        }
    
        end {
            if($found){
                return $group;
            }
            return $found;
        }
    }
    
    Set-FogOU -verbose
    
    

    Hope that helps



  • Well so far it works with using a “1” for “useAD” and “ADDomain” is getting populated. But here is the catch I wasn’t using the create, this was an edit:

        foreach($row2 in $hosts.hostID){
                
        $HostJson = (@{hosts = $row2; createdBy = "groups6"; description = "$($depname[0])"; imageID = "2"; "useAD" = "1"; "ADDomain" = "ede" } | ConvertTo-Json)
        $HostURL = $baseUri+"/host/" + $row2 +"/edit"
            Invoke-RestMethod -Uri $HostURL -Method PUT -Headers $headers -body $HostJson -ContentType "application/json"
         
       }
    

    0_1543277046260_5f0d41b7-e6c5-4968-80a1-a35a440a3424-image.png



  • Rob / Sebastian -

    I am going to attempt to do some testing in this area. I am using @JJ-Fullmer module with great success. You should investigate his work as well. I will let you guys know what I find out. I am snatching up the code and will give it a try on my script. Which version of FOG are you using 1.5.4?

    Mike Parlette


  • Developer

    @RobTitian16 Sorry for the late reply. Your topic is pretty advanced and I do not seem to find the time to dive into it or even test this out myself.

    So you are saying the host is created and you can see it in the web UI, right? What exactly do you mean by “when checking the FOG client AD settings, I see everything is left unchecked”? Are the fields like ADDomain, ADUser and such empty or is it “just” the checkboxes useAD and enforce not being populated?

    If it’s the later I can imagine that it’s some kind of type conversion thing. If you send true in PowerShell way of boolean variable then this might not turn out to be properly transfered to the database. I have not played much with the API Tom created yet but I guess it should understand 1 as true. But that’s just a guess. Have you tried different values yet?

    The other thing that jumped at me is the message in the fog client log: Module is disabled globally on the FOG server



315
Online

5.8k
Users

13.1k
Topics

123.3k
Posts