{"id":19,"date":"2023-03-21T03:27:23","date_gmt":"2023-03-21T03:27:23","guid":{"rendered":"https:\/\/brunocm.azurewebsites.net\/?page_id=19"},"modified":"2025-10-09T14:46:33","modified_gmt":"2025-10-09T12:46:33","slug":"part-4-security-and-filtering","status":"publish","type":"page","link":"https:\/\/brunocm.azurewebsites.net\/?page_id=19","title":{"rendered":"Part 4 &#8211; Security and filtering"},"content":{"rendered":"<h1>Security and filtering<\/h1>\n<p>Now the most complex part of the job!<\/p>\n<p>Of course, it works as-is, but what if your tool works only on a device that has a client and a user select a non-client one?<\/p>\n<p>And what if one user is not allowed to modify a parameter your tool has to change?<\/p>\n<p>It will be frustrating for him to see the option but received an error message as soon as he tries to use it. Especially if you build a complex tool that requires a lot of input that will finally fail at the last step.<\/p>\n<p>The first case is quite simple to cover. Just add 2 lines to your XML file:<\/p>\n<pre>&lt;MatchPattern&gt;True&lt;\/MatchPattern&gt;\n&lt;MatchValueToTest&gt;##SUB:IsClient##&lt;\/MatchValueToTest&gt;<\/pre>\n<p>Now your menu item will only be available if the device selected has his &#8220;IsClient&#8221; parameter sets to &#8220;True&#8221;, otherwise it will be greyed out!<\/p>\n<p>Debug view is of good help to determine which properties you can rely on.<\/p>\n<p>Attention! You can&#8217;t rely on all properties with this method! For example, you can&#8217;t rely safely on the &#8220;IsActive&#8221; or &#8220;ClientActiveStatus&#8221; properties as they are available only if the device is a client of your SCCM infrastructure. If you set a filter on one of these properties and the user selects a device that is not a client, the SCCM console will simply crash trying to check a value of an inexistent property!<\/p>\n<p>To handle this, you have to create a new function in your assembly to check the validity of the device instead, Like this one:<\/p>\n<pre>public static bool checkIfIsActive(object sender, ScopeNode scopeNode, ActionDescription action, ResultObjectBase resultObject)\n{\n   int isActive = 0;\n   try\n   {\n      isActive = ((IResultObject)resultObject).Properties[\"ClientActiveStatus\"].IntegerValue;\n   }\n   catch(NullReferenceException)\n   {\n      return false;\n   }\n\n   if (isActive == 1)\n   {\n      return true;\n   }else\n   {\n      return false;\n   }\n}<\/pre>\n<p>Then you can use another way to filter by calling your function and grey out your menu if it returns a &#8220;false&#8221; value. Your XML file will look close to this:<\/p>\n<pre>&lt;ActionDescription Class=\"AssemblyType\" DisplayName=\"show collections\" MnemonicDisplayName=\"show collections\" Description=\"Shows the list of collection IDs this device is member of\"&gt;\n   &lt;ImagesDescription&gt;\n      &lt;ResourceAssembly&gt;\n         &lt;Assembly&gt;C:\\Program Files (x86)\\myCompany\\myextension\\MyFirstExtension.dll&lt;\/Assembly&gt;\n         &lt;Type&gt;MyFirstExtension.Properties.Resources.resources&lt;\/Type&gt;\n      &lt;\/ResourceAssembly&gt;\n      &lt;ImageResourceName&gt;collinfo&lt;\/ImageResourceName&gt;\n   &lt;\/ImagesDescription&gt;\n   &lt;ShowOn&gt;\n      &lt;string&gt;ContextMenu&lt;\/string&gt;\n      &lt;string&gt;DefaultHomeTab&lt;\/string&gt;\n   &lt;\/ShowOn&gt;\n   &lt;ActionAssembly&gt;\n      &lt;Assembly&gt;C:\\Program Files (x86)\\myCompany\\myextension\\MyFirstExtension.dll&lt;\/Assembly&gt;\n      &lt;Type&gt;MyFirstExtension.DeviceTools&lt;\/Type&gt;\n      &lt;Method&gt;deviceCollections&lt;\/Method&gt;\n   &lt;\/ActionAssembly&gt;\n<strong>   &lt;ActionStateAssembly&gt;<\/strong>\n<strong>      &lt;Assembly&gt;C:\\Program Files (x86)\\myCompany\\myextension\\MyFirstExtension.dll&lt;\/Assembly&gt;<\/strong>\n<strong>      &lt;Type&gt;MyFirstExtension.DeviceTools&lt;\/Type&gt;<\/strong>\n<strong>      &lt;Method&gt;checkIfIsActive&lt;\/Method&gt;\n   <\/strong><strong>&lt;\/ActionStateAssembly&gt;<\/strong>\n&lt;\/ActionDescription&gt;<\/pre>\n<p>Now just imagine that you want to propose this tool to users that are allowed to add to modify boundaries. Sound&#8217;s crazy? Yes, I know! But that&#8217;s just an example.<\/p>\n<p>Explanation In the SDK wasn&#8217;t so clear to me and gave me headaches for several hours. This is what I finally understood. Don&#8217;t hesitate to let me know if I am wrong.<\/p>\n<p>There are two ways to place access permissions on your tool: ClassPermissions and InstancePermissions.<\/p>\n<p>Concretely, if you limit access to a &#8220;collection tool&#8221; for those who have read permission on SMS_Collection using &#8220;InstancePermissions&#8221;, it will be available to users who got the rights specifically on the currently selected object.<\/p>\n<p>On the other hand, using &#8220;ClassPermissions&#8221; will make this tool available if the user has the &#8220;generic&#8221; Read permission on collections.<\/p>\n<p>Not clear? Here are some use-cases.<\/p>\n<ol>\n<li>Target: a collection.<br \/>\nRequired rights: read collection.<br \/>\nThere you can rely on &#8220;InstancePermissions&#8221;. Collections are instances of the securable class SMS_Collection, then you can rely on Instance&#8217;s permission.<\/li>\n<li>Target: a collection.<br \/>\nRequired rights: read boundarygroups (why not?) It seems obvious that you <strong>can&#8217;t<\/strong> rely on &#8220;InstancePermissions&#8221; because you&#8217;re working on a SMS_Collection instance, not on a boundarygroup instance. So you must use &#8220;ClassPermissions&#8221; instead.<\/li>\n<li>Target: a workstation.<br \/>\nRequired rights: modify workstation settings to change variables values and add devices to a collection.<br \/>\nThis is the trickiest one ^^ ! No other choice than using &#8220;ClassPermissions&#8221; because a workstation is an instance of SMS_R_SYSTEM Class which is <strong>not<\/strong> one of the securable class! The required modify permission is placed on the SMS_Collection Class and is named &#8220;Modify Resource&#8221;<\/li>\n<\/ol>\n<p>Hope this will make things clearer to you!<\/p>\n<p>Sadly, the SDK provides only information about permission bits regarding the SMS_Collection class. Fortunately, all information can be found in the SCCM database with a simple query.<\/p>\n<p>As I&#8217;m a nice guy, you will find just here an XLS sheet with the information extracted from an SCCM 2012 R2 database and the query I ran to get them.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2023\/03\/RCT-right-mgmt.xlsx\">RCT-right-mgmt<\/a>\u00a0(xlsx)<\/p>\n<p>It&#8217;s time to use all that.<\/p>\n<p>If you just copy-paste the code sample from the SDK you will face the same issue as I did: it doesn&#8217;t work! There is a missing information: InstancePermission and ClassPermissions must be surrounded by a &lt;SecurityConfiguration&gt; tag.<\/p>\n<p>Here are two samples for use-case 1 and 3:<\/p>\n<p>Case 1:<\/p>\n<pre>&lt;SecurityConfiguration&gt;\n   &lt;InstancePermissions&gt;\n      &lt;SecurityFlagsDetailDescription BitName=\"Read\" BitValue=\"1\" DependsOn=\"1\" \/&gt;\n   &lt;\/InstancePermissions&gt;\n&lt;\/SecurityConfiguration&gt;<\/pre>\n<p>Case 3:<\/p>\n<pre>&lt;SecurityConfiguration&gt;\n   &lt;ClassPermissions&gt;\n      &lt;ActionSecurityDescription ClassObject=\"SMS_Collection\" RequiredPermissions=\"2\" \/&gt;\n      &lt;ActionSecurityDescription ClassObject=\"SMS_Collection\" RequiredPermissions=\"128\" \/&gt;\n   &lt;\/ClassPermissions&gt;\n&lt;\/SecurityConfiguration&gt;<\/pre>\n<p>Of course, you can mix ClassPermission and InstancePermission in a single SecurityConfiguration section.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Security and filtering Now the most complex part of the job! Of course, it works as-is, but what if your tool works only on a device that has a client and a user select a non-client one? And what if one user is not allowed to modify a parameter your tool has to change? It &hellip; <a href=\"https:\/\/brunocm.azurewebsites.net\/?page_id=19\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Part 4 &#8211; Security and filtering&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"_sitemap_exclude":false,"_sitemap_priority":"","_sitemap_frequency":""},"_links":{"self":[{"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/19"}],"collection":[{"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=19"}],"version-history":[{"count":1,"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/19\/revisions"}],"predecessor-version":[{"id":87,"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/19\/revisions\/87"}],"wp:attachment":[{"href":"https:\/\/brunocm.azurewebsites.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=19"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}