Skip to main content
Woohoo! Qlik Community has won “Best in Class Community” in the 2024 Khoros Kudos awards!
Announcements
Join us at Qlik Connect for 3 magical days of learning, networking,and inspiration! REGISTER TODAY and save!
cancel
Showing results for 
Search instead for 
Did you mean: 
Anubhavv
Contributor II
Contributor II

Deallocation of Qlik Sense License

Hello,

I am stuck with a problem, Hope someone can help in sorting this.

We have a User directory connected to our QS environment and it has an attribute "Licensetype" in it. We also have a license rule set up to allocate the license. The rule is ((user.licensetype="Professional")) which automatically allocates the license.

The issue is when we remove the user from the user directory it reflects as an externally removed user in the Qlik user list but the license is still allocated to him and we have to manually deallocate the license.

Is there any way to automatically do this by amending the rules.?

My understanding is that the process flow is like User Directory -> Qlik User List ->professional access rules -> License allocated. Is there a frequency known on which the License rules are evaluated, like is it daily or depend on the user directory task.?  I am thinking of amending the license rule to ((user.licensetype="Professional") and (user.removedExternally='True')) so that users which are removed are not allocated license on next evaluation. Anyone who has tried this approach? 

 

Labels (1)
1 Solution

Accepted Solutions
Levi_Turner
Employee
Employee

Whoops, missed this. Here's an approach (it doesn't handle the token model but for you should be no issue):

#--------------------------------------------------------------------------------------------------------------------------------
#
# Script Name: qlik_sense_purge_removed_externally_users.ps1
# Description: Remove the assigned licenses of users who are marked as removed externally
# Dependency: Qlik-Cli (https://github.com/ahaydon/Qlik-Cli)
# 					
#   Version     Date        Author          Change Notes
#   0.1         2019-08-23  Levi Turner     Initial version
#--------------------------------------------------------------------------------------------------------------------------------

# Helper function for recording timestamps in the logging
function Get-TimeStamp {
    return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}

# More verbose Get-QlikUser function
function Get-QlikUser {
    [CmdletBinding()]
    param (
      [parameter(Position=0,ValueFromPipelinebyPropertyName=$true)]
      [string]$id,
      [string]$filter,
      [switch]$full,
      [switch]$raw
    )
  
    PROCESS {
      $path = "/qrs/user"
      If( $id ) { $path += "/$id" }
      If( $full ) { $path += "/full" }
      If( $raw ) { $rawOutput = $true }
      $result = Invoke-QlikGet $path $filter
      if( $raw -Or $full ) {
        return $result
      } else {
        $properties = @('name','userDirectory','userId','id','removedExternally')
        #if( $full ) { $properties += @('roles','inactive','blacklisted','removedExternally') }
        return $result | Select-Object -Property $properties
      }
    }
}

# Helper function for removing Analyzer licenses; not found in Qlik-Cli when script was being built
function Remove-QlikAnalyzerAccessType {
  [CmdletBinding()]
  param (
    [parameter(Position=0,ValueFromPipelinebyPropertyName=$true)]
    [string]$id
  )

  PROCESS {
    return Invoke-QlikDelete -path "/qrs/license/analyzeraccesstype/$id"
  }
}

function Remove-QlikProfessionalAccessType {
    [CmdletBinding()]
    param (
      [parameter(Position=0,ValueFromPipelinebyPropertyName=$true)]
      [string]$id
    )
  
    PROCESS {
      return Invoke-QlikDelete -path "/qrs/license/professionalaccesstype/$id"
    }
  }
  

# Logging
Set-Location $PSScriptRoot
$logdir = $PSScriptRoot + '\logs'
$logfile = $logdir + "\" + (Get-Date -Format yyyyMMdd) + ".log"
if (!(Test-Path $logdir)){
    New-Item -path $logdir -type directory | Out-Null
}

# Connect to Qlik Sense
Connect-Qlik

# Clearing out Variables
$tokenusers = ''

# Get the version of QRS to figure out license model
$version = Invoke-QlikGet -path /qrs/about
Write-Output "$(Get-TimeStamp) : Build version: $($version.buildversion)" | Out-File -FilePath $logfile -Append

# If the version of QRS is less than April, tokens are being used, otherwise will need to check
if ($($version.buildVersion) -lt '20.4.2.0') {
    Set-Variable -Name "licensemodel" -Value "token"
} else {
    Set-Variable -Name "licensemodel" -Value "variable"
}

# Get list of users assigned named licenses
if ($($licensemodel) -eq 'variable') {
    # if 2018-04 or higher then get the overview to later determine which license model is in effect
    $LicenseOverview = Invoke-QlikGet -path /qrs/License/accesstypeoverview
    Write-Output "$(Get-TimeStamp) : $($LicenseOverview)" | Out-File -FilePath $logfile -Append

    if ($($LicenseOverview).totalTokens -eq '0') {
        # If the totalTokens value in the LicenseOverview response zero, then get Professional User allocations
        Set-Variable -Name "licensemodel" -Value "pa" -Force
        $professionalusers = Invoke-QlikGet -path '/qrs/License/ProfessionalAccessType/full'
        Write-Output "$(Get-TimeStamp) : $($professionalusers.count) professional licenses" | Out-File -FilePath $logfile -Append
        $analyzerusers = Invoke-QlikGet -path '/qrs/License/AnalyzerAccessType/full'
        Write-Output "$(Get-TimeStamp) : $($analyzerusers.count) analyzer licenses" | Out-File -FilePath $logfile -Append

    } else {

        # If the totalTokens value in the LicenseOverview response is non-zero then the token model is in use, get user access pass allocations
        Set-Variable -Name "licensemodel" -Value "token" -Force
        $tokenusers = Invoke-QlikGet -path '/qrs/License/UserAccessType/full'
        Write-Output "$(Get-TimeStamp) : $($tokenusers.count) licenses" | Out-File -FilePath $logfile -Append
    }
} else {
    # if 2018-02 or earlier, then use token model and get user access pass allocations
    Set-Variable -Name "licensemodel" -Value "token" -Force
    $tokenusers = Invoke-QlikGet -path '/qrs/License/UserAccessType/full'
    Write-Output "$(Get-TimeStamp) : $($tokenusers.count) licenses" | Out-File -FilePath $logfile -Append
}
# Remove-QlikProfessionalAccessType 
# Remove-QlikUserAccessType
# Remove-QlikAnalyzerAccessType 

# if/else for iterating over the users
# If the tokenusers variable is null iterate over the p/a users, else token users
if (!$tokenusers) { 
    # P/A Model
    ForEach ($user in $professionalusers) {
        $licenseusers = ''
        $licenseusers = Get-QlikUser -id $user.user.id
        if ($licenseusers.removedExternally -eq 'False') {
            # Users are removedExternally = True
            Write-Output "Removing Professional license for $($user.user.userDirectory)/$($user.user.userId) (User Name: $($user.user.name))" | Out-File -FilePath $logfile -Append
            Remove-QlikProfessionalAccessType -id $user.id
        } else {
            # Users are removedExternally = False
        }
    }
    ForEach ($analyzeruser in $analyzerusers) {
        $analyzerlicenses = ''
        $analyzerlicenses = Get-QlikUser -id $analyzeruser.user.id
        if ($analyzerlicenses.removedExternally -eq 'False') {
            # Users are removedExternally = True
            Write-Output "Removing Analyzer license for $($analyzeruser.user.userDirectory)\$($analyzeruser.user.userId) (User Name: $($analyzeruser.user.name))" | Out-File -FilePath $logfile -Append
            Remove-QlikAnalyzerAccessType -id $analyzeruser.id
        } else {
            # Users are removedExternally = False
        }
    }
} else {
    Write-Host "Token model"
}

 

 If i delete a user from User directory and then from QMC will his license automatically gets deallocated.?

Yes (as well as assign ownership of any apps, sheets, etc to sa_repository).

View solution in original post

11 Replies
Giuseppe_Novello

just to clarify, you want a Security Rule that will deallocate license automatically? Security rules do not have that capability, and systematically there is nothing out of the box that could do that. 

BR

Gio

Giuseppe Novello
Principal Technical Support Engineer @ Qlik
Levi_Turner
Employee
Employee

License assignment is a 1 way process. So the work-flow is broadly like this:

  1. Does the user have a license? If so, use it. If not, then
  2. Is there a rule which would provision the user a license? If so then provision, if not, denied access

So the user would be granted access based on (1).

So the options for license removal would be (a) manually de-allocate or (b) script a periodic de-allocation using the QRS API. For (b), I can come up with some demo code, but what license type are you using (i.e. tokens, professional / analyzer)?

Anubhavv
Contributor II
Contributor II
Author

Hi Gio,

I am looking for Professional access rule which might help in automatically deallocating the license.

Anubhavv
Contributor II
Contributor II
Author

Hi Levi,

Thanks for the insight, I thought that there would be a iteration where the license rule be evaluated and all the allocations are done. Considering that it works only one way i.e only allocation then changing the rule will not help.

Just like we have a checkbox to Allow Access in the Professional access rule section, Can we have a new rule like ((user.removedExternally='True')) and then untick the checkbox to not allow access. Can that work in de allocating license.?

 

I am using professional / analyzer license type, can you help with the QRS API code.? It looks the only way out.?

One more query, if you could help- If i delete a user from User directory and then from QMC will his license automatically gets deallocated.?

Levi_Turner
Employee
Employee

Whoops, missed this. Here's an approach (it doesn't handle the token model but for you should be no issue):

#--------------------------------------------------------------------------------------------------------------------------------
#
# Script Name: qlik_sense_purge_removed_externally_users.ps1
# Description: Remove the assigned licenses of users who are marked as removed externally
# Dependency: Qlik-Cli (https://github.com/ahaydon/Qlik-Cli)
# 					
#   Version     Date        Author          Change Notes
#   0.1         2019-08-23  Levi Turner     Initial version
#--------------------------------------------------------------------------------------------------------------------------------

# Helper function for recording timestamps in the logging
function Get-TimeStamp {
    return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}

# More verbose Get-QlikUser function
function Get-QlikUser {
    [CmdletBinding()]
    param (
      [parameter(Position=0,ValueFromPipelinebyPropertyName=$true)]
      [string]$id,
      [string]$filter,
      [switch]$full,
      [switch]$raw
    )
  
    PROCESS {
      $path = "/qrs/user"
      If( $id ) { $path += "/$id" }
      If( $full ) { $path += "/full" }
      If( $raw ) { $rawOutput = $true }
      $result = Invoke-QlikGet $path $filter
      if( $raw -Or $full ) {
        return $result
      } else {
        $properties = @('name','userDirectory','userId','id','removedExternally')
        #if( $full ) { $properties += @('roles','inactive','blacklisted','removedExternally') }
        return $result | Select-Object -Property $properties
      }
    }
}

# Helper function for removing Analyzer licenses; not found in Qlik-Cli when script was being built
function Remove-QlikAnalyzerAccessType {
  [CmdletBinding()]
  param (
    [parameter(Position=0,ValueFromPipelinebyPropertyName=$true)]
    [string]$id
  )

  PROCESS {
    return Invoke-QlikDelete -path "/qrs/license/analyzeraccesstype/$id"
  }
}

function Remove-QlikProfessionalAccessType {
    [CmdletBinding()]
    param (
      [parameter(Position=0,ValueFromPipelinebyPropertyName=$true)]
      [string]$id
    )
  
    PROCESS {
      return Invoke-QlikDelete -path "/qrs/license/professionalaccesstype/$id"
    }
  }
  

# Logging
Set-Location $PSScriptRoot
$logdir = $PSScriptRoot + '\logs'
$logfile = $logdir + "\" + (Get-Date -Format yyyyMMdd) + ".log"
if (!(Test-Path $logdir)){
    New-Item -path $logdir -type directory | Out-Null
}

# Connect to Qlik Sense
Connect-Qlik

# Clearing out Variables
$tokenusers = ''

# Get the version of QRS to figure out license model
$version = Invoke-QlikGet -path /qrs/about
Write-Output "$(Get-TimeStamp) : Build version: $($version.buildversion)" | Out-File -FilePath $logfile -Append

# If the version of QRS is less than April, tokens are being used, otherwise will need to check
if ($($version.buildVersion) -lt '20.4.2.0') {
    Set-Variable -Name "licensemodel" -Value "token"
} else {
    Set-Variable -Name "licensemodel" -Value "variable"
}

# Get list of users assigned named licenses
if ($($licensemodel) -eq 'variable') {
    # if 2018-04 or higher then get the overview to later determine which license model is in effect
    $LicenseOverview = Invoke-QlikGet -path /qrs/License/accesstypeoverview
    Write-Output "$(Get-TimeStamp) : $($LicenseOverview)" | Out-File -FilePath $logfile -Append

    if ($($LicenseOverview).totalTokens -eq '0') {
        # If the totalTokens value in the LicenseOverview response zero, then get Professional User allocations
        Set-Variable -Name "licensemodel" -Value "pa" -Force
        $professionalusers = Invoke-QlikGet -path '/qrs/License/ProfessionalAccessType/full'
        Write-Output "$(Get-TimeStamp) : $($professionalusers.count) professional licenses" | Out-File -FilePath $logfile -Append
        $analyzerusers = Invoke-QlikGet -path '/qrs/License/AnalyzerAccessType/full'
        Write-Output "$(Get-TimeStamp) : $($analyzerusers.count) analyzer licenses" | Out-File -FilePath $logfile -Append

    } else {

        # If the totalTokens value in the LicenseOverview response is non-zero then the token model is in use, get user access pass allocations
        Set-Variable -Name "licensemodel" -Value "token" -Force
        $tokenusers = Invoke-QlikGet -path '/qrs/License/UserAccessType/full'
        Write-Output "$(Get-TimeStamp) : $($tokenusers.count) licenses" | Out-File -FilePath $logfile -Append
    }
} else {
    # if 2018-02 or earlier, then use token model and get user access pass allocations
    Set-Variable -Name "licensemodel" -Value "token" -Force
    $tokenusers = Invoke-QlikGet -path '/qrs/License/UserAccessType/full'
    Write-Output "$(Get-TimeStamp) : $($tokenusers.count) licenses" | Out-File -FilePath $logfile -Append
}
# Remove-QlikProfessionalAccessType 
# Remove-QlikUserAccessType
# Remove-QlikAnalyzerAccessType 

# if/else for iterating over the users
# If the tokenusers variable is null iterate over the p/a users, else token users
if (!$tokenusers) { 
    # P/A Model
    ForEach ($user in $professionalusers) {
        $licenseusers = ''
        $licenseusers = Get-QlikUser -id $user.user.id
        if ($licenseusers.removedExternally -eq 'False') {
            # Users are removedExternally = True
            Write-Output "Removing Professional license for $($user.user.userDirectory)/$($user.user.userId) (User Name: $($user.user.name))" | Out-File -FilePath $logfile -Append
            Remove-QlikProfessionalAccessType -id $user.id
        } else {
            # Users are removedExternally = False
        }
    }
    ForEach ($analyzeruser in $analyzerusers) {
        $analyzerlicenses = ''
        $analyzerlicenses = Get-QlikUser -id $analyzeruser.user.id
        if ($analyzerlicenses.removedExternally -eq 'False') {
            # Users are removedExternally = True
            Write-Output "Removing Analyzer license for $($analyzeruser.user.userDirectory)\$($analyzeruser.user.userId) (User Name: $($analyzeruser.user.name))" | Out-File -FilePath $logfile -Append
            Remove-QlikAnalyzerAccessType -id $analyzeruser.id
        } else {
            # Users are removedExternally = False
        }
    }
} else {
    Write-Host "Token model"
}

 

 If i delete a user from User directory and then from QMC will his license automatically gets deallocated.?

Yes (as well as assign ownership of any apps, sheets, etc to sa_repository).

Rehan
Creator III
Creator III

HOw to use this script:

bi2run_olli
Partner - Contributor II
Partner - Contributor II

Levi, 

thanks for this snippet 🙂

From the point of view of licenses perspective:
Would this be a conceivable approach to (re)assign licenses to different users?  Eg, day by day.

My customer is using the signed license key without Quarantine.

Thank you

 

\olli

bi2run_olli
Partner - Contributor II
Partner - Contributor II

anyone? 

 

🙂

Levi_Turner
Employee
Employee

That approach would run afoul of the majority of contractual terms customers agree to. I'd suggest working with the account manager for your customer to clarify what the expected terms are.