{"id":13623752,"url":"https://github.com/ATVWGS/tenant-management-framework","last_synced_at":"2025-04-15T20:32:17.788Z","repository":{"id":43119573,"uuid":"406687176","full_name":"ATVWGS/tenant-management-framework","owner":"ATVWGS","description":"The Tenant Management Framework is a Powershell module that is able to create, update and delete resources or settings via the Microsoft Graph API.","archived":false,"fork":false,"pushed_at":"2024-05-22T14:19:52.000Z","size":3564,"stargazers_count":18,"open_issues_count":1,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-05-22T14:59:24.161Z","etag":null,"topics":["azuread","desired-state-configuration","o365","powershell","powershell-module"],"latest_commit_sha":null,"homepage":"","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ATVWGS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-15T09:02:21.000Z","updated_at":"2024-06-04T07:40:54.839Z","dependencies_parsed_at":"2023-12-20T12:48:53.266Z","dependency_job_id":"50b8ff2b-4a00-4209-a274-4a4fa1ff0e5a","html_url":"https://github.com/ATVWGS/tenant-management-framework","commit_stats":null,"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ATVWGS%2Ftenant-management-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ATVWGS%2Ftenant-management-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ATVWGS%2Ftenant-management-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ATVWGS%2Ftenant-management-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ATVWGS","download_url":"https://codeload.github.com/ATVWGS/tenant-management-framework/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249148081,"owners_count":21220469,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azuread","desired-state-configuration","o365","powershell","powershell-module"],"created_at":"2024-08-01T21:01:35.263Z","updated_at":"2025-04-15T20:32:17.763Z","avatar_url":"https://github.com/ATVWGS.png","language":"PowerShell","funding_links":[],"categories":["PowerShell"],"sub_categories":[],"readme":"![Logo](./assets/images/logo.png)\r\n\r\nTenant Management Framework \u003c!-- omit in toc --\u003e\r\n===========================\r\n\r\n![GitHub](https://img.shields.io/github/license/ATVWGS/tenant-management-framework)\r\n[![TMF](https://img.shields.io/powershellgallery/v/TMF.svg?label=TMF)](https://www.powershellgallery.com/packages/TMF/)\r\n\r\n# 1. Introduction \r\nThe Tenant Management Framework is a Powershell module that is able to create, update and\r\ndelete resources or settings via the Microsoft Graph API. The module provides simple\r\nPowershell cmdlets to deploy and manage a set of predefined configuration files. The basic idea is\r\nbased on the [Active Directory Management Framework](https://admf.one).\r\n\r\n![Showcase](./assets/images/showcase.gif)\r\n\r\n## 1.1. Goals\r\n- Deliver a PowershellModule with standardized\r\ncommands to deploy Tenant configurations\r\n- Provide a default configuration file format that is easy\r\nto read and to manage\r\n- Give the administrators pre-build configurations with\r\nbest practices\r\n- Enable administrators to create a reusable tenant\r\nconfigurations\r\n\r\n## 1.2. Benefits\r\n- Reproducable configuration\r\n- Easy readable, storable and shareable configurations\r\n- Enforced change documentation and versioning by adding a source control\r\n- Enables staging concept\r\n- Less prone to human error\r\n- Increased efficiency\r\n\r\n# 2. Getting started\r\n## 2.1. Installation\r\nCheckout the [Powershell Gallery](https://www.powershellgallery.com/packages/TMF/)!\r\n\r\n## 2.2. Importing\r\nYou can simply import the module using *Import-Module TMF* if the module has been placed in one of your module directory. (Checkout $env:PSModulePath)\r\nIt is also possible to directly import the module using *Import-Module \u003cPATH_TO_MODULE\u003e/TMF/TMF.psd1*\r\n\r\n## 2.3. Authentication\r\nWe are using the Microsoft.Graph module to make changes in the targeted Azure AD Tenant. This module also has a sub-module for authentication against Microsoft Graph. You can connect using the following command.\r\n```powershell\r\nPS\u003e Connect-MgGraph -Scopes \"User.Read.All\", \"Group.ReadWrite.All\"\r\n```\r\nhttps://github.com/microsoftgraph/msgraph-sdk-powershell\r\n\r\nPlease make sure you are connected to the correct Tenant before invoking configurations! \r\n\r\nThe required scopes depend on what components (resources) you want to configure.\r\n\r\n| Resource                                                         | Required scopes                                                                                                              |\r\n|------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|\r\n| AccessReviews\t\t\t\t\t\t\t\t\t\t\t\t\t   | AccessReview.ReadWrite.All\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  |\r\n| AdministrativeUnits                                             | AdministrativeUnit.ReadWrite.All, Directory.AccessAsUser.All, RoleManagement.ReadWrite.Directory                             |\r\n| Agreements (Terms of Use)                                        | Agreement.ReadWrite.All                                                                                                      |\r\n| AuthenticationContextClassReferences                             | AuthenticationContext.ReadWrite.All, Policy.ReadWrite.ConditionalAccess\t\t\t\t\t\t\t\t\t\t\t\t\t  |\r\n| ConditionalAccessPolicies                                      | Policy.ReadWrite.ConditionalAccess, Policy.Read.All, RoleManagement.Read.Directory, Application.Read.All, Agreement.Read.All |\r\n| CrossTenantAccess (policy, defaultSettings, partnerSettings)     | Policy.ReadWrite.CrossTenantAccess   \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  |\r\n| CustomSecurityAttributes                                       | CustomSecAttributeDefinition.ReadWrite.All                                                                                   |\r\n| DirectoryRoles\t\t\t\t\t\t\t\t\t\t\t\t   | RoleManagement.ReadWrite.Directory                                                                                           |\r\n| DirectorySettings\t\t\t\t\t\t\t\t\t\t\t   | Directory.ReadWrite.All\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  |\r\n| EntitlementManagement (Access Packages, Access Package Catalogs)| EntitlementManagement.ReadWrite.All                                                                                          |\r\n| Groups                                                           | Group.ReadWrite.All, GroupMember.ReadWrite.All                                                                               |\r\n| NamedLocations                                                  | Policy.ReadWrite.ConditionalAccess                                                                                           |\r\n| OrganizationalBrandings\t\t\t\t\t\t\t\t\t\t   | OrganizationalBranding.ReadWrite.All, Organization.ReadWrite.All\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  |\r\n| Policies (authentication/authorization policies)                 | Policy.ReadWrite.AuthenticationMethod, Policy.ReadWrite.Authorization, Policy.ReadWrite.AuthenticationFlows                  |\r\n| RoleManagement (assignments, definitions, management policies)  | RoleManagement.ReadWrite.Directory, Directory.AccessAsUser.All, RoleEligibilitySchedule.ReadWrite.Directory,                 |\r\n|                                                                  | RoleAssignmentSchedule.ReadWrite.Directory, RoleManagementPolicy.ReadWrite.Directory                                      |\r\n| Users                                                            | User.ReadWrite.All                                                                                                           |\r\n\r\n\r\nYou can also use *Get-TmfRequiredScope* to get the required scopes and combine it with *Connect-MgGraph*.\r\n```powershell\r\nPS\u003e Connect-MgGraph -Scopes (Get-TmfRequiredScope -All)\r\nPS\u003e Connect-MgGraph -Scopes (Get-TmfRequiredScope -Groups -RoleManagement)\r\n```\r\n\r\n## 2.4. Configurations\r\nA Tenant Management Framework configuration is a collection of resource definition files in a predefined folder structure. The definition files describe instances of different resource types (eg. Groups, Conditional Access Policies, Named Locations) in the [JavaScript Object Notation (.json)](https://de.wikipedia.org/wiki/JavaScript_Object_Notation). \r\n\r\n### 2.4.1. configuration.json\r\nConfigurations always contain a *configuration.json* file at the root level. This file contains the properties that describe a configuration and is automatically created when using [*New-TmfConfiguration*](#323-how-can-i-create-a-configuration).\r\n\r\n```json\r\n{\r\n    \"Name\":  \"Example Configuration\",\r\n    \"Description\":  \"This is a example configuration.\",\r\n    \"Author\":  \"Mustermann, Max\",\r\n    \"Weight\":  50,\r\n    \"Prerequisite\":  [\r\n                        \"Default Configuration\"\r\n                     ]\r\n}\r\n```\r\n\r\n| Property     | Description                                                                      \r\n|--------------|----------------------------------------------------------------------------------\r\n| Name         | The name of the configuration. Must be uniqe when using multiple configurations.\r\n| Description  | Description of the configuration. Here you can discribe, for which tenants this configurations should be used.\r\n| Author       | The responsible team or person for this configuration.\r\n| Weight       | When activating multiple configurations, the configuration with the highest weight is loaded last. This means that a resource definition will be overwriten, if the last configuration contains a definition with the same displayName.\r\n| Prerequisite | With this setting you can define a relationship to an another configuration by the configuration name. For example when a configurations requires a baseline configuration. It is also possible to allow different configurations as prerequisite using an OR-operator. This can be helpful when the target tenants are slightly different. For example: TenantConfig1 || TenantConfig2 || TenantConfig3\r\n\r\n#### 2.4.1.1. Prerequisite OR-operator example\r\n\r\n```json\r\n{\r\n    \"Name\":  \"Example Configuration\",\r\n    \"Description\":  \"This is a example configuration.\",\r\n    \"Author\":  \"Mustermann, Max\",\r\n    \"Weight\":  50,\r\n    \"Prerequisite\":  [\r\n                        \"Default_Config\",\r\n                        \"DEV_Tenant_Config || QA_Tenant_Config || PROD_Tenant_Config\"\r\n                     ]\r\n}\r\n```\r\n\r\n### 2.4.2. Folder structure\r\nFor each supported resource type there is a subfolder. These subfolders always contain an empty .json file and example.md. \r\n\r\nThe empty *.json* file is used to define resource instances. As an example a resource instance can be the definition of an Azure AD Security group or a Conditional Access policy. You can place multiple *.json* in a single resource type subfolder. By creating multiple *.json* files it is possible to structure resource definitions in a understandable way.\r\n\r\n **The folder names are mandatory for the functionality of the framework! Folders that do not represent a supported resource type will be ignored!**\r\n\r\nThe *example.md* file contains example resource instances and further information.\r\n\r\n\r\n```markdown\r\n# Folder structure of a newly created configuration\r\n├───accessReviews\r\n│       accessReviews.json\r\n│       example.md\r\n│\r\n├───administrativeUnits\r\n│       administrativeUnits.json\r\n│       example.md\r\n│\r\n├───agreements\r\n│   │   agreements.json\r\n│   │   example.md\r\n│   │\r\n│   └───files\r\n│           Example Terms of Use.pdf\r\n│\r\n├───authenticationContextClassReferences\r\n│       authenticationContextClassReferences.json\r\n│       example.md\r\n│\r\n├───conditionalAccessPolicies\r\n│       example.md\r\n│       policies.json\r\n│\r\n├───crossTenantAccess\r\n│   ├───crossTenantAccessDefaultSettings\r\n│   │       crossTenantAccessDefaultSettings.json\r\n│   │       example.md\r\n│   │       \r\n│   ├───crossTenantAccessPartnerSettings\r\n│   │       crossTenantAccessPartnerSettings.json\r\n│   │       example.md\r\n│   │       \r\n│   └───crossTenantAccessPolicy\r\n│           crossTenantAccessPolicy.json\r\n│           example.md\r\n│\r\n├───customSecurityAttributes\r\n│   ├───attributeSets\r\n│   │       attributeSets.json\r\n│   │       example.md\r\n│   │\r\n│   └───customSecurityAttributeDefinitions\r\n│           customSecurityAttributeDefinitions.json\r\n│           example.md\r\n|\r\n├───directoryRoles\r\n│       directoryRoles.json\r\n│       example.md\r\n│\r\n├───directorySettings\r\n│       directorySettings.json\r\n│       example.md\r\n│\r\n├───entitlementManagement\r\n│   ├───accessPackageCatalogs\r\n│   │       accessPackageCatalogs.json\r\n│   │       example.md\r\n│   │\r\n│   └───accessPackages\r\n│           accessPackages.json\r\n│           example.md\r\n│\r\n├───groups\r\n│       example.md\r\n│       groups.json\r\n│\r\n├───namedLocations\r\n│       example.md\r\n│       namedLocations.json\r\n│\r\n├───organizationalBrandings\r\n│       example.md\r\n│       organizationalBrandings.json\r\n│\r\n├───policies\r\n│   ├───appManagementPolicies\r\n│   │       appManagementPolicies.json\r\n│   │       example.md\r\n│   │\r\n│   ├───authenticationFlowsPolicies\r\n│   │       authenticationFlowsPolicies.json\r\n│   │       example.md\r\n│   │\r\n│   ├───authenticationMethodsPolicies\r\n│   │       authenticationMethodsPolicies.json\r\n│   │       example.md\r\n│   │\r\n│   ├───authenticationStrengthPolicies\r\n│   │       authenticationStrengthPolicies.json\r\n│   │       example.md\r\n│   │\r\n│   ├───authorizationPolicies\r\n│   │       authorizationPolicies.json\r\n│   │       example.md\r\n│   │\r\n│   └───tenantAppManagementPolicy\r\n│           tenantAppManagementPolicy.json\r\n│           example.md\r\n│\r\n├───roleManagement\r\n│   ├───roleAssignments\r\n│   │       roleAssignments.json\r\n│   │       example.md\r\n│   │\r\n│   ├───roleDefinitions\r\n│   │       roleDefinitions.json\r\n│   │       example.md\r\n│   │\r\n│   ├───roleManagementPolicies\r\n│   │       roleManagementPolicies.json\r\n│   │       example.md\r\n│   │\r\n│   └───roleManagementPolicyRuleTemplates\r\n│           roleManagementPolicyRuleTemplates.json\r\n│           example.md\r\n│\r\n├───stringMappings\r\n│       stringMappings.json\r\n│\r\n└───users\r\n        example.md\r\n        users.json\r\n```\r\n\r\n### 2.4.3. How can I create a configuration?\r\nYou can create new configuration by simple using the function *New-TmfConfiguration*. This function will create the required folder structure and the *configuration.json* file in the given location.\r\n```powershell\r\nPS\u003e New-TmfConfiguration -Name \"Example Configuration\" -Description \"This is an example configuration for the Tenant Management Framework!\" -Author \"Mustermann, Max\" -Weight 50 -OutPath \"$env:USERPROFILE\\Desktop\\Example_Configuration\" -Force\r\n\r\n[16:02:04][New-TmfConfiguration] Creating configuration directory C:\\Users\\username\\Desktop\\Example_Configuration. [DONE]\r\n[16:02:04][New-TmfConfiguration] Copying template structure to C:\\Users\\username\\Desktop\\Example_Configuration. [DONE]\r\n[16:02:05][Activate-TmfConfiguration] Activating Example Configuration (C:\\Users\\username\\Desktop\\Example_Configuration\\configuration.json). This configuration will be considered when applying Tenant configuration. [DONE]\r\n[16:02:05][Activate-TmfConfiguration] Sorting all activated configurations by weight. [DONE]\r\n[16:02:05][New-TmfConfiguration] Creation has finished! Have fun! [DONE]\r\n```\r\n\r\nThe *-Force* paramter tells the functions to automatically create the target directory or overwrite a configuration at the target directory. In the example it would create the folder \"Example_Configuration\".\r\n\r\nA newly created configuration will be automatically activated. This means when using *Load-TmfConfiguration* the defined resources are loaded from the *.json* files and can be directly invoked or tested against the connected tenant.\r\n\r\n### 2.4.4. How can I activate or deactivate a configuration?\r\nTo invoke or test defined resources against a tenant, you need to activate the containing configuration at the beginning. This means that you have to tell the TMF which configurations you want it to consider in the next steps.\r\n\r\nThis activation can simply be done using *Activate-TmfConfiguration*.\r\n```powershell\r\nPS\u003e Activate-TmfConfiguration \"$env:USERPROFILE\\Desktop\\Example_Configuration\" -Force\r\n\r\n[16:10:46][Activate-TmfConfiguration] Activating Example Configuration (C:\\Users\\username\\Desktop\\Example_Configuration\\configuration.json). This configuration will be considered when applying Tenant configuration. [DONE]\r\n[16:10:46][Activate-TmfConfiguration] Sorting all activated configurations by weight. [DONE]\r\n```\r\n\r\nYou can use *Get-TmfActiveConfiguration* to checkout all already activated configurations.\r\n```powershell\r\nPS\u003e Get-TmfActiveConfiguration\r\n\r\nName         : Example Configuration\r\nPath         : C:\\Users\\username\\Desktop\\Example_Configuration\r\nDescription  : This is an example configuration for the Tenant Management Framework!\r\nAuthor       : Mustermann, Max\r\nWeight       : 50\r\nPrerequisite : {}\r\n```\r\n\r\nTo deactivate a configuration use *Deactivate-TmfConfiguration*. After deactivating a configuration the TMF won't considere it in further steps.\r\n```powershell\r\nDeactivate-TmfConfiguration -Name \"Example Configuration\" # By name\r\nDeactivate-TmfConfiguration -Path \"$env:USERPROFILE\\Desktop\\Example_Configuration\" # By path\r\nDeactivate-TmfConfiguration -All # Or all activated configurations!\r\n\r\n\r\n[16:18:08][Deactivate-TmfConfiguration] Deactivating Example Configuration. This configuration will not be considered when applying Tenant configuration. [DONE]\r\n```\r\n\r\n### 2.4.5. Storing configurations\r\nWe recommend you to store configurations in a git repository. By adding a source control system you get enforced documentation and versioning.\r\nIn our case we store multiple configurations (Default configuration, DEV configuration, QA configuration and so on) in a single Azure DevOps repository.\r\n\r\n## 2.5. General functions\r\n### 2.5.1. Load-TmfConfiguration - Load definition files from configurations\r\nThe *Load-TmfConfiguration* function checks all *.json* files from the activated configurations and registers them into a runtime store. Technically this is the same process as if you use a register function for a single resource type (eg. *Register-TmfGroup*). All loaded resource definitions are considered when using test or invoke functions.\r\n\r\n```powershell\r\nPS\u003e Load-TmfConfiguration\r\n```\r\n\r\n### 2.5.2. Get-TmfDesiredConfiguration - Show the current desired configuration\r\n\r\nYou can check the currently loaded desired configuration with *Get-TmfDesiredConfiguration*. This returns the desired configuration as a hashtable.\r\n\r\n```powershell\r\nPS\u003e Get-TmfDesiredConfiguration\r\n\r\nName                           Value\r\n----                           -----\r\naccessPackages                 {}\r\ngroups                         {@{displayName=Some group; description=This is a security group; groupTypes=System.String[]; securityEnabled=True; mailEnabled=False; mailNickname=someGroupForMembers; present=True... \r\nnamedLocations                 {}\r\naccessPackageCatalogs          {}\r\nconditionalAccessPolicies      {}\r\nagreements                     {}\r\nstringMappings                 {}\r\n\r\n# You can also checkout single resource definitions\r\nPS\u003e (Get-TmfDesiredConfiguration)[\"groups\"]\r\n\r\ndisplayName     : Some group\r\ndescription     : This is a security group\r\ngroupTypes      : {}\r\nsecurityEnabled : True\r\nmailEnabled     : False\r\nmailNickname    : someGroupForMembers\r\npresent         : True\r\nsourceConfig    : Example Configuration\r\nowners          : {group.owner@example.org}\r\nmembers         : {max.mustermann@example.org}\r\n\r\n# Filtering is also possible with Where-Object\r\n(Get-TmfDesiredConfiguration)[\"groups\"] | Where-Object {$_.displayName -eq \"Some group\"}\r\n\r\ndisplayName     : Some group\r\ndescription     : This is a security group\r\ngroupTypes      : {}\r\nsecurityEnabled : True\r\nmailEnabled     : False\r\nmailNickname    : someGroupForMembers\r\npresent         : True\r\nsourceConfig    : Example Configuration\r\nowners          : {group.owner@example.org}\r\nmembers         : {max.mustermann@example.org}\r\n```\r\n\r\n### 2.5.3. Test-Tmf* - Test definitions against Graph\r\nIt is possible to run tests for a single resource type, for an resouce type group (eg. Entitlement Management) or for a whole tenant.\r\n\r\nIf you want to only test your configured groups, you can use *Test-TmfGroup*. This will only consider all definitions of the resource type \"groups\".\r\n\r\n```powershell\r\nPS\u003e Test-TmfGroup\r\n\r\nActionType           : Create\r\nResourceType         : Group\r\nResourceName         : Example group\r\nChanges              :\r\nTenant               : TENANT_NAME\r\nTenantId             : d369908f-8803-46bc-90cb-3c82854ddf93\r\nDesiredConfiguration : @{displayName=Example group; description=This is an example security group; groupTypes=System.String[]; securityEnabled=True; mailEnabled=False; mailNickname=someGroupForMembers;\r\n                       present=True; sourceConfig=Example Configuration}\r\nGraphResource        :\r\n```\r\n\r\nThe resource type specific test functions always return test result objects. These objects show you, which actions are required in your tenant, to achive the desired configuration.\r\n\r\nAdditionally you can test only specific resources of a resource type group by adding the -specificResources parameter. This parameter accepts a string array including wildcards.\r\n\r\n```powershell\r\nPS\u003e Test-TmfGroup -specificResources \"Example *\"\r\n\r\nActionType           : Create\r\nResourceType         : Group\r\nResourceName         : Example group\r\nChanges              :\r\nTenant               : TENANT_NAME\r\nTenantId             : d369908f-8803-46bc-90cb-3c82854ddf93\r\nDesiredConfiguration : @{displayName=Example group; description=This is an example security group; groupTypes=System.String[]; securityEnabled=True; mailEnabled=False; mailNickname=someGroupForMembers;\r\n                       present=True; sourceConfig=Example Configuration}\r\nGraphResource        :\r\n```\r\n\r\nYou can test all available resource types using *Test-TmfTenant*. The *Test-TmfTenant* function and also all resource type group (eg. *Test-TmfEntitlementManagement*) functions automatically beautify the test results.\r\n\r\n```powershell\r\nPS\u003e Test-TmfTenant\r\n\r\n[20:35:51][Test-TmfTenant] Currently connected to \u003cTENANT_NAME\u003e (d369908f-XXXX-XXXX-90cb-3c82854ddf93)\r\n[20:35:52][Test-TmfTenant] Starting tests for groups\r\n[20:35:52][TMF] [Tenant: TENANT_NAME][Group Resource: Example group] Required Action (Create)\r\n```\r\n\r\nWith *Beautify-TmfTestResult* you are able to beautify the results of any resouce type specific test command.\r\n\r\n```powershell\r\nPS\u003e Test-TmfGroup | Beautify-TmfTestResult\r\n\r\n[20:37:34][TMF] [Tenant: TENANT_NAME][Group Resource: Example group] Required Action (Create)\r\n```\r\n\r\n### 2.5.4. Invoke-Tmf* - Perform actions against Graph\r\nThe invoke functions are available for a single resource type, for a resouce type group (eg. Entitlement Management) or for the whole tenant. These functions are capable of creating, updating or deleting resources using Microsoft Graph. The executed actions depend on the results the test functions return.\r\n\r\nExample based on Access Packages:\r\n- *Invoke-TmfAccessPackage:* Only invokes actions for the defined Access Packages\r\n- *Invoke-TmfEntitlementManagement:* Invokes the required actions for Access Packages and also for all other resource types required for Entitlement Management.\r\n- *Invoke-TmfTenant*: Invokes the required actions for each resource type defined in your configurations.\r\n\r\n```powershell\r\nPS\u003e Invoke-TmfGroup\r\n\r\n[20:44:17][Invoke-TmfGroup] [Tenant: TENANT_NAME][Group Resource: Example group] Required Action (Create)\r\n[20:44:17][Invoke-TmfGroup] [Tenant: TENANT_NAME][Group Resource: Example group] Completed.\r\n\r\nPS\u003e Invoke-TmfTenant\r\n\r\n[20:49:46][Invoke-TmfTenant] Currently connected to TENANT_NAME (d369908f-8803-46bc-90cb-3c82854ddf93)\r\nIs this the correct tenant? [y/n]: y\r\n[20:49:48][Invoke-TmfTenant] Invoking groups\r\n[20:49:49][Invoke-TmfGroup] [Tenant: TENANT_NAME][Group Resource: Example group] Required Action (NoActionRequired)\r\n[20:49:49][Invoke-TmfGroup] [Tenant: TENANT_NAME][Group Resource: Example group] Completed.\r\n```\r\n\r\nAdditionally you can invoke only specific resources of a resource type group by adding the -specificResources parameter. This parameter accepts a string array including wildcards.\r\n\r\n```powershell\r\nPS\u003e Invoke-TmfGroup -specificResources \"Example*\"\r\n\r\n[20:44:17][Invoke-TmfGroup] [Tenant: TENANT_NAME][Group Resource: Example group] Required Action (Create)\r\n[20:44:17][Invoke-TmfGroup] [Tenant: TENANT_NAME][Group Resource: Example group] Completed.\r\n```\r\n\r\n### 2.5.5. Register-Tmf* - Add definitions temporarily\r\nYou can use the register functions to manually register a resource definition. When registering a resource definition it will be added to the desired configuration. \r\n\r\nA resource must be registered before the Tenant Management Framework can test it's configuration against the Tenant.\r\n\r\n*The displayName property must be uniqe in the desired configuration!* Resources are searched by the displayName.\r\n\r\n\r\n## 2.6. Resources types\r\nThe supported resources are based on the endpoints and resource types provided by [Microsoft Graph](https://developer.microsoft.com/en-us/graph).\r\nMost of the definition files use the json syntax that the API endpoint also uses.\r\n\r\n### 2.6.1. General properties\r\nAll main resource types support the following general properties.\r\n\r\n| Name | Type | Use case | Not supported by |\r\n|------|------|----------|------------------|\r\n| displayName | string | Is the mainly used identifier of a resource. We are always using the displayName to search resources. | |\r\n| oldNames | string[] | Allows you to rename a resource by searching it using an old name. **Example:** When group \"Group A\" should now be called \"Group B\", you can specify \"Group A\" in the oldNames property and set the displayName to \"Group B\". The TMF will update the displayName in the tenant automatically. | entitlementManagement (accessPackages, accessPackageCatalogs, accessPackageResource, accessPackageAssignmentPolicies) |\r\n| present | bool | Is _true_ by default. If you set it to _false_, the resource is deleted. | |\r\n\r\n### 2.6.2. Groups\r\nAn example definition for a simple Azure AD security group with a predefined member and a predefined owner.\r\n\r\n```json\r\n{   \r\n    \"displayName\": \"Some group\",\r\n    \"description\": \"This is a security group\",\r\n    \"groupTypes\": [],        \r\n    \"securityEnabled\": true,\r\n    \"mailEnabled\": false,\r\n    \"mailNickname\": \"someGroupForMembers\",\r\n    \"members\": [\"max.mustermann@example.org\"],\r\n    \"owners\": [\"group.owner@example.org\"],\r\n    \"present\": true\r\n}\r\n```\r\n\r\nPlease check the [Groups example.md](./TMF/internal/data/configuration/groups/example.md) for further information.\r\n\r\n### 2.6.3. Conditional Access Policies\r\nAn example policy definition that would affect all members of a group to accept ToU and and provide MFA.\r\n\r\n```json\r\n{\r\n    \"displayName\" : \"Require MFA and ToU for all members of Some group\",\r\n    \"excludeGroups\": [\"Some group for CA\"],\r\n    \"excludeUsers\": [\"max.mustermann@TENANT_NAME.onmicrosoft.com\"],        \r\n    \"includeApplications\": [\"All\"],        \r\n    \"includeLocations\": [\"All\"],\r\n    \"clientAppTypes\": [\"browser\", \"mobileAppsAndDesktopClients\"],\r\n    \"includePlatforms\": [\"All\"],\r\n    \"grantControls\": {\r\n        \"builtInControls\": [\"mfa\"],\r\n        \"operator\": \"AND\",\r\n        \"termsOfUse\": [\"ToU for Some group\"]\r\n    },\r\n    \"state\" : \"enabledForReportingButNotEnforced\",\r\n    \"present\" : true\r\n}\r\n```\r\n\r\nAn example policy definition that would enable an authenticationStrengthPolicy for filtered apps.\r\n\r\n```json\r\n{\r\n    \"displayName\" : \"Require authentication strength for filtered apps\",\r\n    \"excludeGroups\": [\"Some group for CA\"],\r\n    \"excludeUsers\": [\"max.mustermann@TENANT_NAME.onmicrosoft.com\"],        \r\n    \"includeLocations\": [\"All\"],\r\n    \"applicationFilter\": {\r\n        \"mode\": \"include\",\r\n        \"rule\": \"CustomSecurityAttribute.TestSet2_TestAttribute2 -contains \\\"Value4\\\" -or CustomSecurityAttribute.TestSet2_TestAttribute3 -contains \\\"Value1\\\"\"\r\n    },\r\n    \"clientAppTypes\": [\"All\"],\r\n    \"includePlatforms\": [\"All\"],\r\n    \"grantControls\": {\r\n        \"authenticationStrength\": \"TestASP\",\r\n        \"builtInControls\": [],\r\n        \"operator\": \"OR\"\r\n    },\r\n    \"state\" : \"enabledForReportingButNotEnforced\",\r\n    \"present\" : true\r\n}\r\n```\r\n\r\nPlease check the [Conditional Access Policy example.md](./TMF/internal/data/configuration/conditionalAccessPolicies/example.md) for further information.\r\n\r\n### 2.6.4. Named Locations\r\nAn example IP Named Location definition.\r\n\r\n```json\r\n{\r\n    \"type\": \"ipNamedLocation\",\r\n    \"displayName\": \"Untrusted IP named location\",\r\n    \"isTrusted\": false,\r\n    \"ipRanges\": [\r\n        {\r\n            \"@odata.type\": \"#microsoft.graph.iPv4CidrRange\",\r\n            \"cidrAddress\": \"12.34.221.11/22\"\r\n        },\r\n        {\r\n            \"@odata.type\": \"#microsoft.graph.iPv6CidrRange\",\r\n            \"cidrAddress\": \"2001:0:9d38:90d6:0:0:0:0/63\"\r\n        }\r\n    ],\r\n    \"present\": true\r\n}\r\n```\r\n\r\nPlease check the [Named Location example.md](./TMF/internal/data/configuration/namedLocations/example.md) for further information.\r\n\r\n### 2.6.5. Agreements (Terms of Use)\r\n\r\nAn example Agreement definition with a single PDF file added.\r\n\r\n```json\r\n{\r\n  \"displayName\": \"An example agreement with a single files\",\r\n  \"isViewingBeforeAcceptanceRequired\": true,\r\n  \"isPerDeviceAcceptanceRequired\": false,\r\n  \"userReacceptRequiredFrequency\": \"P90D\",\r\n  \"termsExpiration\": {\r\n    \"startDateTime\": \"05.03.2021 00:00:00\",\r\n    \"frequency\": \"PT1M\"\r\n  },\r\n  \"files\": [\r\n    {\r\n      \"fileName\": \"Example Terms of Use.pdf\",\r\n      \"language\": \"en\",\r\n      \"isDefault\": true,\r\n      \"filePath\": \"files/Example Terms of Use.pdf\"\r\n    }\r\n  ],\r\n  \"present\": true\r\n}\r\n```\r\n\r\nPlease check the [Agreements example.md](./TMF/internal/data/configuration/agreements/example.md) for further information.\r\n\r\n### 2.6.6. Entitlement Management\r\nEntitlement Management can be done by the following resource types. For further information about Azure AD Entitlement Management you can read the official documentation: https://docs.microsoft.com/en-us/azure/active-directory/governance/entitlement-management-overview.\r\n\r\n#### 2.6.6.1. Access Package Catalogs\r\nA simple Access Package Catalog definition.\r\n\r\n```json\r\n{    \r\n    \"displayName\": \"Access package catalog for testing\",\r\n    \"description\": \"Sample access package catalog\",\r\n    \"isExternallyVisible\": false,\r\n    \"present\": true\r\n}\r\n```\r\n\r\nPlease check the [Access Package Catalogs example.md](./TMF/internal/data/configuration/entitlementManagement/accessPackageCatalogs/example.md) for further information.\r\n\r\n#### 2.6.6.2. Access Packages\r\n\r\n```json\r\n{\t\r\n    \"displayName\":  \"Sample package\",\r\n    \"oldNames\": [],\r\n    \"description\":  \"This is a sample access package.\",\r\n    \"isHidden\":  false,\r\n    \"isRoleScopesVisible\":  true,\r\n    \"catalog\":  \"Sample catalog\",\r\n    \"present\":  true,\r\n    \"accessPackageResources\":  [\r\n        {\r\n            \"originSystem\":  \"AadGroup\",\r\n            \"resourceRole\":  \"Member\",\r\n            \"resourceIdentifier\":  \"Some group\"\r\n        }\r\n    ],\r\n    \"assignmentPolicies\": [\r\n        {\r\n            \"displayName\": \"Sample assignment policy\",\r\n            \"description\": \"Access Package Assignment Policy has been created with Tenant Management Framework\",\r\n            \"allowedTargetScope\": \"specificDirectoryUsers\",\r\n            \"present\": true,\r\n            \"specificAllowedTargets\": [\r\n                {\r\n                    \"reference\": \"Some group\",\r\n                    \"type\": \"groupMembers\",\r\n                    \"description\": \"Some group\"\r\n                }\r\n            ],\r\n            \"expiration\": {\r\n                \"endDateTime\": null,\r\n                \"duration\": \"P90D\",\r\n                \"type\": \"afterDuration\"\r\n            },\r\n            \"requestorSettings\": {\r\n                \"enableTargetsToSelfAddAccess\": true,\r\n                \"enableTargetsToSelfUpdateAccess\": false,\r\n                \"enableTargetsToSelfRemoveAccess\": true,\r\n                \"allowCustomAssignmentSchedule\": true,\r\n                \"enableOnBehalfRequestorsToAddAccess\": true,\r\n                \"enableOnBehalfRequestorsToUpdateAccess\": false,\r\n                \"enableOnBehalfRequestorsToRemoveAccess\": false,\r\n                \"onBehalfRequestors\": []\r\n            },\r\n            \"requestApprovalSettings\": {\r\n                \"isApprovalRequiredForAdd\": true,\r\n                \"isApprovalRequiredForUpdate\": true,\r\n                \"stages\": [\r\n                    {\r\n                        \"durationBeforeAutomaticDenial\": \"P14D\",\r\n                        \"isApproverJustificationRequired\": true,\r\n                        \"isEscalationEnabled\": false,\r\n                        \"durationBeforeEscalation\": \"P5D\",\r\n                        \"primaryApprovers\": [\r\n                            {\r\n                                \"reference\": \"Some group\",\r\n                                \"type\": \"groupMembers\",\r\n                                \"description\": \"Some group\"\r\n                            }\r\n                        ],\r\n                        \"fallbackPrimaryApprovers\": [],\r\n                        \"escalationApprovers\": [\r\n                            {\r\n                                \"reference\": \"foo.bar@tenant.onmicrosoft.com\",\r\n                                \"type\": \"singleUser\"\r\n                            }\r\n                        ],\r\n                        \"fallbackEscalationApprovers\": []\r\n                    }\r\n                ]\r\n            },\r\n            \"reviewSettings\": {\r\n                \"isEnabled\": true,\r\n                \"expirationBehavior\": \"keepAccess\",\r\n                \"isRecommendationEnabled\": true,\r\n                \"isReviewerJustificationRequired\": true,\r\n                \"isSelfReview\": true,\r\n                \"schedule\": {\r\n                    \"startDateTime\": \"2023-04-18T09:34:49.4485321Z\",\r\n                    \"expiration\": {\r\n                        \"endDateTime\": null,\r\n                        \"duration\": \"P7D\",\r\n                        \"type\": \"afterDuration\"\r\n                    },\r\n                    \"recurrence\": {\r\n                        \"pattern\": {\r\n                            \"type\": \"absoluteMonthly\",\r\n                            \"interval\": 1,\r\n                            \"month\": 0,\r\n                            \"dayOfMonth\": 0,\r\n                            \"daysOfWeek\": [],\r\n                            \"firstDayOfWeek\": null,\r\n                            \"index\": null\r\n                        },\r\n                        \"range\": {\r\n                            \"type\": \"noEnd\",\r\n                            \"numberOfOccurrences\": 0,\r\n                            \"recurrenceTimeZone\": null,\r\n                            \"startDate\": null,\r\n                            \"endDate\": null\r\n                        }\r\n                    }\r\n                },\r\n                \"primaryReviewers\": [\r\n                    {\r\n                        \"reference\": \"Some group\",\r\n                        \"type\": \"groupMembers\",\r\n                        \"description\": \"Some group\"\r\n                    }                    \r\n                ],\r\n                \"fallbackReviewers\": []\r\n            }\r\n        }\r\n    ]\r\n}\r\n```\r\n\r\nPlease check the [Access Packages example.md](./TMF/internal/data/configuration/entitlementManagement/accessPackages/example.md) for further information.\r\n\r\n##### Access Package Resources \u003c!-- omit in toc --\u003e \r\nAccess Package Resources are directly defined in the depending Access Package definition.\r\n\r\n##### Access Package Assignment Policies \u003c!-- omit in toc --\u003e\r\nAccess Package Assignment Policies are directly defined the depending Access Package definition.\r\n\r\n### 2.6.7. Administrative Units\r\nA simple Administrative Unit definition.\r\n\r\n```json\r\n{\r\n    \"displayName\": \"Administrative Unit for Testing\",\r\n    \"description\": \"This AU is used for testing\",\r\n    \"visibility\": \"Public\",\r\n    \"members\": [\"max.mustermann@tmacdev.onmicrosoft.com\"],\r\n    \"groups\": [],\r\n    \"scopedRoleMembers\": [\r\n        {\r\n            \"role\": \"Groups Administrator\",\r\n            \"identity\": \"Max Mustermann\"\r\n        },\r\n        {\r\n            \"role\": \"User Administrator\",\r\n            \"identity\": \"Max Mustermann\"\r\n        }\r\n    ],\r\n    \"present\": true\r\n}\r\n```\r\n\r\nPlease check the [Administrative Units example.md](./TMF/internal/data/configuration/administrativeUnits/example.md) for further information.\r\n\r\n### 2.6.8. Access Reviews\r\n\r\n```json\r\n{\r\n    \"displayName\": \"Displayname of the access review\",\r\n    \"present\": true,\r\n    \"scope\": {\r\n      \"type\": \"group\",\r\n      \"reference\": \"some group\"\r\n    },\r\n    \"reviewers\": [\r\n        {\r\n            \"type\": \"groupMembers\",\r\n            \"reference\":\"some group\"\r\n        }\r\n    ],\r\n    \"settings\": {\r\n        \"mailNotificationsEnabled\": true,\r\n        \"reminderNotificationsEnabled\": true,\r\n        \"justificationRequiredOnApproval\": true,\r\n        \"defaultDecisionEnabled\": false,\r\n        \"defaultDecision\": \"None\",\r\n        \"instanceDurationInDays\": 14,\r\n        \"autoApplyDecisionsEnabled\": false,\r\n        \"recommendationsEnabled\": true,\r\n        \"recurrence\": {\r\n            \"pattern\": {\r\n                \"type\": \"absoluteMonthly\",\r\n                \"interval\": 3,\r\n                \"month\": 0,\r\n                \"dayOfMonth\": 0,\r\n                \"daysOfWeek\": [],\r\n                \"firstDayOfWeek\": \"sunday\",\r\n                \"index\": \"first\"\r\n            },\r\n            \"range\": {\r\n                \"type\": \"noEnd\",\r\n                \"numberOfOccurrences\": 0,\r\n                \"recurrenceTimeZone\": null,\r\n                \"startDate\": \"2022-03-01\",\r\n                \"endDate\": \"9999-12-31\"\r\n            }\r\n        }\r\n    }\r\n  }\r\n```\r\nPlease check the [Access Reviews example.md](./TMF/internal/data/configuration/accessReviews/example.md) for further information.\r\n\r\n### 2.6.9. Directory Roles\r\n\r\n```json\r\n{\r\n    \"present\": true,\r\n    \"displayName\": \"Role displayname\",\r\n    \"members\": [\r\n        {\r\n            \"type\": \"group\",\r\n            \"reference\": \"some group\"\r\n        },\r\n        {\r\n            \"type\": \"singleUser\",\r\n            \"reference\": \"givenname.sn@tenant.onmicrosoft.com\"\r\n        }\r\n    ]\r\n}\r\n\r\n```\r\nPlease check the [Directory Roles example.md](./TMF/internal/data/configuration/directoryRoles/example.md) for further information.\r\n\r\n\r\n### 2.6.10. Policies\r\n\r\n#### 2.6.10.1. authenticationFlowsPolicies\r\n\r\n```json\r\n[\r\n\t{\r\n\t\t\"displayName\": \"Authentication flows policy\",\r\n\t\t\"selfServiceSignUpEnabled\": false\r\n\t}\r\n]\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/policies/authenticationFlowsPolicies/example.md) for further information.\r\n\r\n\r\n#### 2.6.10.2. authenticationMethodsPolicies\r\n\r\n```json\r\n[\r\n\t{\r\n\t\t\"displayName\": \"Authentication Methods Policy\",\r\n\t\t\"registrationEnforcement\": {\r\n\t\t\t\"authenticationMethodsRegistrationCampaign\": {\r\n\t\t\t\t\"snoozeDurationInDays\": 1,\r\n\t\t\t\t\"state\": \"default\",\r\n\t\t\t\t\"excludeTargets\": [],\r\n\t\t\t\t\"includeTargets\": [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\"id\": \"all_users\",\r\n\t\t\t\t\t\t\"targetType\": \"group\",\r\n\t\t\t\t\t\t\"targetedAuthenticationMethod\": \"microsoftAuthenticator\"\r\n\t\t\t\t\t}\r\n\t\t\t\t]\r\n\t\t\t}\r\n\t\t},\r\n\t\t\"authenticationMethodConfigurations\": [\r\n\t\t\r\n\t\t\t{\r\n\t\t\t\t\"id\": \"Fido2\",\r\n\t\t\t\t\"state\": \"disabled\",\r\n\t\t\t\t\"isSelfServiceRegistrationAllowed\": true,\r\n\t\t\t\t\"isAttestationEnforced\": true\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"id\": \"MicrosoftAuthenticator\",\r\n\t\t\t\t\"state\": \"disabled\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"id\": \"Sms\",\r\n\t\t\t\t\"state\": \"disabled\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"id\": \"TemporaryAccessPass\",\r\n\t\t\t\t\"state\": \"disabled\",\r\n\t\t\t\t\"defaultLifetimeInMinutes\": 60,\r\n\t\t\t\t\"defaultLength\": 8,\r\n\t\t\t\t\"minimumLifetimeInMinutes\": 60,\r\n\t\t\t\t\"maximumLifetimeInMinutes\": 480,\r\n\t\t\t\t\"isUsableOnce\": false\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"id\": \"Email\",\r\n\t\t\t\t\"state\": \"enabled\",\r\n\t\t\t\t\"allowExternalIdToUseEmailOtp\": \"enabled\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"id\": \"X509Certificate\",\r\n\t\t\t\t\"state\": \"disabled\",\r\n\t\t\t\t\"certificateUserBindings\": [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\"x509CertificateField\": \"PrincipalName\",\r\n\t\t\t\t\t\t\"userProperty\": \"onPremisesUserPrincipalName\",\r\n\t\t\t\t\t\t\"priority\": 1\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\"x509CertificateField\": \"RFC822Name\",\r\n\t\t\t\t\t\t\"userProperty\": \"userPrincipalName\",\r\n\t\t\t\t\t\t\"priority\": 2\r\n\t\t\t\t\t}\r\n\t\t\t\t],\r\n\t\t\t\t\"authenticationModeConfiguration\": {\r\n\t\t\t\t\t\"x509CertificateAuthenticationDefaultMode\": \"x509CertificateSingleFactor\",\r\n\t\t\t\t\t\"rules\": []\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t]\r\n\t}\r\n]\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/policies/authenticationMethodsPolicies/example.md) for further information.\r\n\r\n\r\n#### 2.6.10.3. authenticationStrengthPolicies\r\n\r\n```json\r\n[\r\n    {\r\n        \"present\": true,\r\n        \"displayName\": \"TestASP\",\r\n        \"description\": \"Test Authentication Strength Policies\",\r\n        \"allowedCombinations\": [\r\n            \"deviceBasedPush\"\r\n        ]\r\n    }\r\n]\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/policies/authenticationStrengthPolicies/example.md) for further information.\r\n\r\n#### 2.6.10.4. authorizationPolicies\r\n\r\n```json\r\n\r\n[\r\n\t{\r\n\t\t\"displayName\": \"Authorization Policy\",\r\n        \"allowInvitesFrom\": \"adminsAndGuestInviters\",\r\n        \"allowedToSignUpEmailBasedSubscriptions\": false,\r\n        \"allowedToUseSSPR\": true,\r\n        \"allowEmailVerifiedUsersToJoinOrganization\": false,\r\n        \"blockMsolPowerShell\": false,\r\n        \"guestUserRole\": \"Guest User\",\r\n        \"allowedToCreateApps\": false,\r\n        \"allowedToCreateSecurityGroups\": false,\r\n        \"allowedToReadOtherUsers\": true,\r\n\t\t\"allowedToReadBitlockerKeysForOwnedDevice\": true,\r\n        \"permissionGrantPolicyIdsAssignedToDefaultUserRole\": []\r\n\t}\r\n]\r\n\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/policies/authorizationPolicies/example.md) for further information.\r\n\r\n#### 2.6.10.5. appManagementPolicies\r\n\r\n```json\r\n\r\n[\r\n\t{\r\n        \"displayName\": \"appManagementPolicyTest\",\r\n        \"description\": \"Test policy for appManagement\",\r\n        \"isEnabled\": true,\r\n        \"restrictions\": {\r\n            \"passwordCredentials\": [\r\n                {\r\n                    \"restrictionType\": \"passwordAddition\",\r\n                    \"maxLifetime\": null,\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2023-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"passwordLifetime\",\r\n                    \"maxLifetime\": \"P365D\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2023-01-01T10:37:00Z\"\r\n                }\r\n            ],\r\n            \"keyCredentials\": [\r\n                {\r\n                    \"restrictionType\": \"asymmetricKeyLifetime\",\r\n                    \"maxLifetime\": \"P90D\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2023-01-01T10:37:00Z\"\r\n                }\r\n            ]\r\n        },\r\n        \"appliesTo\": [\r\n            \"application1\",\r\n            \"application2\"\r\n        ],\r\n        \"present\": true\t\t\r\n    }\r\n]\r\n\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/policies/appManagementPolicies/example.md) for further information.\r\n\r\n#### 2.6.10.6. tenantAppManagementPolicies\r\n\r\n```json\r\n[\r\n    {\r\n        \"displayname\": \"Default app management tenant policy\",\r\n        \"description\": \"Default tenant policy that enforces app management restrictions on applications and service principals. To apply policy to targeted resources, create a new policy under appManagementPolicies collection.\",\r\n        \"isEnabled\": true,\r\n        \"applicationRestrictions\": {\r\n            \"passwordCredentials\": [\r\n                {\r\n                    \"restrictionType\": \"passwordAddition\",\r\n                    \"maxLifetime\": null,\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2021-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"passwordLifetime\",\r\n                    \"maxLifetime\": \"P4DT12H30M5S\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2017-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"symmetricKeyAddition\",\r\n                    \"maxLifetime\": null,\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2021-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"customPasswordAddition\",\r\n                    \"maxLifetime\": null,\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2015-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"symmetricKeyLifetime\",\r\n                    \"maxLifetime\": \"P40D\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2015-01-01T10:37:00Z\"\r\n                }\r\n            ],\r\n            \"keyCredentials\":[\r\n                {\r\n                    \"restrictionType\": \"asymmetricKeyLifetime\",\r\n                    \"maxLifetime\": \"P30D\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2015-01-01T10:37:00Z\"\r\n                },\r\n            ]\r\n        },\r\n        \"servicePrincpialRestrictions\": {\r\n            \"passwordCredentials\": [\r\n                {\r\n                    \"restrictionType\": \"passwordAddition\",\r\n                    \"maxLifetime\": null,\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2021-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"passwordLifetime\",\r\n                    \"maxLifetime\": \"P4DT12H30M5S\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2017-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"symmetricKeyAddition\",\r\n                    \"maxLifetime\": null,\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2021-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"customPasswordAddition\",\r\n                    \"maxLifetime\": null,\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2015-01-01T10:37:00Z\"\r\n                },\r\n                {\r\n                    \"restrictionType\": \"symmetricKeyLifetime\",\r\n                    \"maxLifetime\": \"P40D\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2015-01-01T10:37:00Z\"\r\n                }\r\n            ],\r\n            \"keyCredentials\":[\r\n                {\r\n                    \"restrictionType\": \"asymmetricKeyLifetime\",\r\n                    \"maxLifetime\": \"P30D\",\r\n                    \"restrictForAppsCreatedAfterDateTime\": \"2015-01-01T10:37:00Z\"\r\n                },\r\n            ]\r\n        }\r\n    }\r\n]\r\n\r\n\r\n```\r\n\r\n### 2.6.11. roleManagement\r\n\r\n#### 2.6.11.1. roleAssignments\r\n\r\n##### Eligible role assignment for a group on a directory role with no expiration\r\n```json\r\n{\r\n    \"present\": true,\r\n    \"type\": \"eligible\",\r\n    \"principalReference\": \"Group name\",\r\n    \"principalType\": \"group\",\r\n    \"roleReference\": \"directory role name\",\r\n    \"directoryScopeReference\": \"/\",\r\n    \"directoryScopeType\": \"directory\",\r\n    \"startDateTime\": \"2022-04-28T00:00:00.00Z\",\r\n    \"expirationType\": \"noExpiration\"\r\n}\r\n```\r\n##### Eligible role assignment for a group on an administrativeUnit with no expiration\r\n```json\r\n{\r\n    \"present\": true,\r\n    \"type\": \"eligible\",\r\n    \"principalReference\": \"Group name\",\r\n    \"principalType\": \"group\",\r\n    \"roleReference\": \"directory role name\",\r\n    \"directoryScopeReference\": \"name of administrativeUnit\",\r\n    \"directoryScopeType\": \"administrativeUnit\",\r\n    \"startDateTime\": \"2022-04-28T00:00:00.00Z\",\r\n    \"expirationType\": \"noExpiration\"\r\n}\r\n```\r\n##### Eligible role assignment for a group on the owner role on subscription level with endTime\r\n```json\r\n{\r\n    \"present\": true,\r\n    \"type\": \"eligible\",\r\n    \"principalReference\": \"Some group\",\r\n    \"principalType\": \"group\",\r\n    \"roleReference\": \"Owner\",\r\n    \"subscriptionReference\": \"Subscription name\",\r\n    \"scopeReference\": \"Subscription name\",\r\n    \"scopeType\": \"subscription\",\r\n    \"startDateTime\": \"2022-03-30T00:00:00.00Z\",\r\n    \"expirationType\": \"AfterDateTime\",\r\n    \"endDateTime\": \"2023-03-30T00:00:00.00Z\"\r\n}\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/roleManagement/roleAssignments/example.md) for further information.\r\n\r\n\r\n#### 2.6.11.2. roleDefinitions\r\n\r\n##### Custom role definition for Azure Resources\r\n```json\r\n\r\n{\r\n    \"present\": true,\r\n    \"displayName\": \"Some role name\",\r\n    \"description\": \"Some description\",\r\n    \"subscriptionReference\": \"Subscription name\",\r\n    \"assignableScopes\": [\r\n        \"/subscriptions/subscriptionID\",\r\n        \"/subscriptions/subscriptionID/ResourceGroups/resourceGroupName\"\r\n    ],\r\n    \"permissions\": [\r\n        {\r\n            \"actions\": [\r\n                \"Microsoft.Resources/subscriptions/resourceGroups/write\",\r\n                \"Microsoft.Resources/subscriptions/resourceGroups/delete\"\r\n            ],\r\n            \"notActions\": [],\r\n            \"dataActions\": [],\r\n            \"notDataActions\": []\r\n        }\r\n    ]\r\n}\r\n```\r\n##### Custom role definition for EntraID\r\n```json\r\n\r\n{\r\n    \"present\": true,\r\n    \"displayName\": \"Some role name\",\r\n    \"description\": \"Some description\",\r\n    \"rolePermissions\": [\r\n        {\r\n            \"allowedResourceActions\": [\r\n                \"microsoft.directory/groups/standard/read\",\r\n                \"microsoft.directory/groups/memberOf/read\",\r\n                \"microsoft.directory/groups/members/read\",\r\n                \"microsoft.directory/groups/owners/read\"\r\n            ],\r\n            \"condition\": null\r\n        }\r\n    ]\r\n}\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/roleManagement/roleDefinitions/example.md) for further information.\r\n\r\n\r\n#### 2.6.11.3. roleManagementPolicies\r\n\r\n##### RoleManagementPolicy for directory role without approval\r\n```json\r\n{\r\n    \"roleReference\": \"directory role name\",\r\n    \"activationApprover\": [],\r\n    \"scopeReference\": \"/\",\r\n    \"scopeType\": \"directory\",\r\n    \"ruleTemplate\": \"some rule template\"\r\n}\r\n```\r\n\r\n##### RoleManagementPolicy for AzureResource role on subscription level with approver\r\n```json\r\n{\r\n    \"roleReference\": \"role name\",\r\n    \"subscriptionReference\": \"subscription name\",\r\n    \"scopeReference\": \"subscription name\",\r\n    \"scopeType\": \"subscription\",\r\n    \"activationApprover\": [\r\n        {\r\n            \"reference\": \"userPrincipalName\",\r\n            \"type\": \"user\"\r\n        }\r\n    ],\r\n    \"ruleTemplate\": \"some rule template\"\r\n}\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/roleManagement/roleManagementPolicies/example.md) for further information.\r\n\r\n\r\n#### 2.6.11.4. roleManagementPolicyRuleTemplates\r\n\r\nroleManagementPolicyRuleTemplates include all rules but the \"Approval_EndUser_Assignment\". The approvers are set within the roleManagementPolicies configurations.\r\n\r\n##### RoleManagementPolicy ruleset with maximum 9 months eligible assignment possible, permanent active assignment possible and activation duration of 12 hours\r\n```json\r\n{\r\n    \"displayName\": \"AzureAD_Tier0\",\r\n    \"rules\": [\r\n      {\r\n        \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyExpirationRule\",\r\n        \"id\": \"Expiration_Admin_Eligibility\",\r\n        \"isExpirationRequired\": true,\r\n        \"maximumDuration\": \"P270D\",\r\n        \"target\": {\r\n            \"caller\": \"Admin\",\r\n            \"operations\": [\r\n                \"All\"\r\n            ],\r\n            \"level\": \"Eligibility\",\r\n            \"inheritableSettings\": [],\r\n            \"enforcedSettings\": []\r\n        }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyEnablementRule\",\r\n          \"id\": \"Enablement_Admin_Eligibility\",\r\n          \"enabledRules\": [],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Eligibility\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Admin_Admin_Eligibility\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Admin\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Eligibility\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Requestor_Admin_Eligibility\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Requestor\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Eligibility\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Approver_Admin_Eligibility\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Approver\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Eligibility\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyExpirationRule\",\r\n          \"id\": \"Expiration_Admin_Assignment\",\r\n          \"isExpirationRequired\": false,\r\n          \"maximumDuration\": \"P270D\",\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyEnablementRule\",\r\n          \"id\": \"Enablement_Admin_Assignment\",\r\n          \"enabledRules\": [\r\n              \"Justification\"\r\n          ],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Admin_Admin_Assignment\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Admin\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Requestor_Admin_Assignment\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Requestor\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Approver_Admin_Assignment\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Approver\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"Admin\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyExpirationRule\",\r\n          \"id\": \"Expiration_EndUser_Assignment\",\r\n          \"isExpirationRequired\": true,\r\n          \"maximumDuration\": \"PT12H\",\r\n          \"target\": {\r\n              \"caller\": \"EndUser\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyEnablementRule\",\r\n          \"id\": \"Enablement_EndUser_Assignment\",\r\n          \"enabledRules\": [\r\n              \"Justification\"\r\n          ],\r\n          \"target\": {\r\n              \"caller\": \"EndUser\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyAuthenticationContextRule\",\r\n          \"id\": \"AuthenticationContext_EndUser_Assignment\",\r\n          \"isEnabled\": false,\r\n          \"claimValue\": null,\r\n          \"target\": {\r\n              \"caller\": \"EndUser\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Admin_EndUser_Assignment\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Admin\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"EndUser\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Requestor_EndUser_Assignment\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Requestor\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"EndUser\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      },\r\n      {\r\n          \"@odata.type\": \"#microsoft.graph.unifiedRoleManagementPolicyNotificationRule\",\r\n          \"id\": \"Notification_Approver_EndUser_Assignment\",\r\n          \"notificationType\": \"Email\",\r\n          \"recipientType\": \"Approver\",\r\n          \"notificationLevel\": \"All\",\r\n          \"isDefaultRecipientsEnabled\": true,\r\n          \"notificationRecipients\": [],\r\n          \"target\": {\r\n              \"caller\": \"EndUser\",\r\n              \"operations\": [\r\n                  \"All\"\r\n              ],\r\n              \"level\": \"Assignment\",\r\n              \"inheritableSettings\": [],\r\n              \"enforcedSettings\": []\r\n          }\r\n      }\r\n    ]\r\n  }\r\n  ```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/roleManagement/roleManagementPolicyRuleTemplates/example.md) for further information.\r\n\r\n### 2.6.12 Custom security attributes\r\n\r\n#### 2.6.12.1 attributeSets\r\n\r\n```json\r\n    {\r\n\t\t\"displayName\": \"TestSet\",\r\n\t\t\"description\": \"Attribute set for testing\",\r\n\t\t\"maxAttributesPerSet\": 3,\r\n\t\t\"present\": true\r\n\t}\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/customSecurityAttributes/attributeSets/example.md) for further information.\r\n\r\n#### 2.6.12.2 customSecurityAttributeDefinitions\r\n\r\n```json\r\n    {\r\n        \"attributeSet\": \"AttributeSetForTest\",\r\n        \"displayName\": \"TestAttribute1\",\r\n        \"description\": \"Test attribute 1\",\r\n        \"isCollection\": false,\r\n        \"isSearchable\": true,\r\n        \"present\": true,\r\n        \"status\": \"Available\",\r\n        \"type\": \"String\",\r\n        \"usePreDefinedValuesOnly\": true,\r\n        \"allowedValues\": [\r\n            {\r\n                \"displayName\": \"Value1\",\r\n                \"isActive\": true\r\n            },\r\n            {\r\n                \"displayName\": \"Value2\",\r\n                \"isActive\": false\r\n            }\r\n        ]\r\n    }\r\n```\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/customSecurityAttributes/customSecurityAttributDefinitions/example.md) for further information.\r\n\r\n### 2.6.13. AuthenticationContextClassReferences\r\n\r\n```json\r\n[\r\n    {\r\n        \"displayName\": \"authenticationContext example\",\r\n        \"id\": \"c1\",\r\n        \"description\": \"authenticationContext example\",\r\n        \"isAvailable\": true,\r\n        \"present\": true\r\n    }\r\n]\r\n\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/authenticationContextClassReferences/example.md) for further information.\r\n\r\n### 2.6.14. CrossTenantAccess\r\n\r\n#### 2.6.14.1 CrossTenantAccessDefaultSettings\r\n\r\n```json\r\n[\r\n    {\r\n        \"displayName\": \"CrossTenantAccessDefaultSettings\",\r\n        \"inboundTrust\": {\r\n            \"isMfaAccepted\": false,\r\n            \"isCompliantDeviceAccepted\": false,\r\n            \"isHybridAzureADJoinedDeviceAccepted\": false\r\n        },\r\n        \"b2bCollaborationOutbound\": {\r\n            \"usersAndGroups\": {\r\n                \"accessType\": \"allowed\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllUsers\",\r\n                        \"targetType\": \"user\"\r\n                    }\r\n                ]\r\n            },\r\n            \"applications\": {\r\n                \"accessType\": \"allowed\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllApplications\",\r\n                        \"targetType\": \"application\"\r\n                    }\r\n                ]\r\n            }\r\n        },\r\n        \"b2bCollaborationInbound\": {\r\n            \"usersAndGroups\": {\r\n                \"accessType\": \"allowed\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllUsers\",\r\n                        \"targetType\": \"user\"\r\n                    }\r\n                ]\r\n            },\r\n            \"applications\": {\r\n                \"accessType\": \"allowed\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllApplications\",\r\n                        \"targetType\": \"application\"\r\n                    }\r\n                ]\r\n            }\r\n        },\r\n        \"b2bDirectConnectOutbound\": {\r\n            \"usersAndGroups\": {\r\n                \"accessType\": \"blocked\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllUsers\",\r\n                        \"targetType\": \"user\"\r\n                    }\r\n                ]\r\n            },\r\n            \"applications\": {\r\n                \"accessType\": \"blocked\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllApplications\",\r\n                        \"targetType\": \"application\"\r\n                    }\r\n                ]\r\n            }\r\n        },\r\n        \"b2bDirectConnectInbound\": {\r\n            \"usersAndGroups\": {\r\n                \"accessType\": \"blocked\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllUsers\",\r\n                        \"targetType\": \"user\"\r\n                    }\r\n                ]\r\n            },\r\n            \"applications\": {\r\n                \"accessType\": \"blocked\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllApplications\",\r\n                        \"targetType\": \"application\"\r\n                    }\r\n                ]\r\n            }\r\n        },\r\n        \"automaticUserConsentSettings\": {\r\n            \"inboundAllowed\": false,\r\n            \"outboundAllowed\": false\r\n        },\r\n        \"tenantRestrictions\": {\r\n            \"devices\": null,\r\n            \"usersAndGroups\": {\r\n                \"accessType\": \"blocked\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllUsers\",\r\n                        \"targetType\": \"user\"\r\n                    }\r\n                ]\r\n            },\r\n            \"applications\": {\r\n                \"accessType\": \"blocked\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"AllApplications\",\r\n                        \"targetType\": \"application\"\r\n                    }\r\n                ]\r\n            }\r\n        },\r\n        \"invitationRedemptionIdentityProviderConfiguration\": {\r\n            \"primaryIdentityProviderPrecedenceOrder\": [\r\n                \"azureActiveDirectory\",\r\n                \"externalFederation\",\r\n                \"socialIdentityProviders\"\r\n            ],\r\n            \"fallbackIdentityProvider\": \"defaultConfiguredIdp\"\r\n        }\r\n    }\r\n]\r\n\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/crossTenantAccess/crossTenantAccessDefaultSettings/example.md) for further information.\r\n\r\n#### 2.6.14.2 CrossTenantAccessPartnerSettings\r\n\r\n```json\r\n[\r\n    {\r\n        \"displayName\": \"tenantName\",\r\n        \"tenantId\": \"tenantId\",\r\n        \"present\": true,\r\n        \"inboundTrust\": {\r\n            \"isMfaAccepted\": false,\r\n            \"isCompliantDeviceAccepted\": true,\r\n            \"isHybridAzureADJoinedDeviceAccepted\": false\r\n        },\r\n        \"b2bCollaborationOutbound\": null,\r\n        \"b2bCollaborationInbound\": {\r\n            \"usersAndGroups\": {\r\n                \"accessType\": \"allowed\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"some GroupID\",\r\n                        \"targetType\": \"group\"\r\n                    }\r\n                ]\r\n            },\r\n            \"applications\": {\r\n                \"accessType\": \"allowed\",\r\n                \"targets\": [\r\n                    {\r\n                        \"target\": \"some ApplicationId\",\r\n                        \"targetType\": \"application\"\r\n                    }\r\n                ]\r\n            }\r\n        },\r\n        \"b2bDirectConnectOutbound\": null,\r\n        \"b2bDirectConnectInbound\": null,\r\n        \"tenantRestrictions\": null,\r\n        \"invitationRedemptionIdentityProviderConfiguration\": null,\r\n        \"automaticUserConsentSettings\": {\r\n            \"inboundAllowed\": null,\r\n            \"outboundAllowed\": true\r\n        }\r\n    }\r\n]\r\n\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/crossTenantAccess/crossTenantAccessPartnerSettings/example.md) for further information.\r\n\r\n#### 2.6.14.3. CrossTenantAccessPolicy\r\n\r\n```json\r\n[\r\n    {\r\n        \"displayName\": \"CrossTenantAccessPolicy\",\r\n        \"allowedCloudEndpoints\": [\"partner.microsoftonline.cn\"]\r\n    }\r\n]\r\n\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/crossTenantAccess/crossTenantAccessPolicy/example.md) for further information.\r\n\r\n### 2.6.15. DirectoryRoles\r\n\r\n```json\r\n[\r\n    {\r\n        \"present\": true,\r\n        \"displayName\": \"Role displayname\",\r\n        \"members\": [\r\n            {\r\n                \"type\": \"group\",\r\n                \"reference\": \"some group\"\r\n            },\r\n            {\r\n                \"type\": \"singleUser\",\r\n                \"reference\": \"givenname.sn@tenant.onmicrosoft.com\"\r\n            }\r\n        ]\r\n    }\r\n]\r\n\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/directoryRoles/example.md) for further information.\r\n\r\n### 2.6.16. DirectorySettings\r\n\r\n#### Example for directory setting \"Application\"\r\n```json\r\n{\r\n    \"displayName\": \"Application\",\r\n    \"present\": true,\r\n    \"EnableAccessCheckForPrivilegedApplicationUpdates\": true\r\n}\r\n```\r\n\r\n#### Example for directory setting \"Password Rule Settings\" with disabled onPrem settings\r\n```json\r\n{\r\n    \"displayName\": \"Password Rule Settings\",\r\n    \"present\": true,\r\n    \"BannedPasswordCheckOnPremisesMode\": \"Audit|Enforced\",\r\n    \"EnableBannedPasswordCheckOnPremises\": false,\r\n    \"EnableBannedPasswordCheck\": true,\r\n    \"LockoutDurationInSeconds\": 60,\r\n    \"LockoutThreshold\": 5,\r\n    \"BannedPasswordList\": \"password\"\r\n}\r\n```\r\n\r\n#### Example for directory setting \"Group.Unified\"\r\n```json\r\n{\r\n    \"displayName\": \"Group.Unified\",\r\n    \"present\": true,\r\n    \"NewUnifiedGroupWritebackDefault\": true,\r\n    \"EnableMIPLabels\": true,\r\n    \"CustomBlockedWordsList\": \"word1,word2\",\r\n    \"EnableMSStandardBlockedWords\": false,\r\n    \"ClassificationDescriptions\": \"Public:Information with no restrictions,Internal:Information that is intended for internal use only and not for the general public\",\r\n    \"DefaultClassification\": \"Internal\",\r\n    \"PrefixSuffixNamingRequirement\": \"[pre][suffix]\",\r\n    \"AllowGuestsToBeGroupOwner\": false,\r\n    \"AllowGuestsToAccessGroups\": true,\r\n    \"GuestUsageGuidelinesUrl\": \"https://someUrl.com\",\r\n    \"GroupCreationAllowedGroupId\": \"\",\r\n    \"AllowToAddGuests\": true,\r\n    \"UsageGuidelinesUrl\": \"https://someUrl.com\",\r\n    \"ClassificationList\": \"Internal,Public\",\r\n    \"EnableGroupCreation\": true\r\n}\r\n```\r\n\r\n#### Example for directory setting \"Prohibited Names Settings\"\r\n```json\r\n{\r\n    \"displayName\": \"Prohibited Names Settings\",\r\n    \"present\": true,\r\n    \"CustomBlockedSubStringsList\": \"substring1,substring2\",\r\n    \"CustomBlockedWholeWordsList\": \"word1,word2\"\r\n}\r\n```\r\n\r\n#### Example for directory setting \"Custom Policy Settings\"\r\n```json\r\n{\r\n    \"displayName\": \"Custom Policy Settings\",\r\n    \"present\": true,\r\n    \"CustomConditionalAccessPolicyUrl\": \"https://someUrl.com\"\r\n}\r\n```\r\n\r\n#### Example for directory setting \"Consent Policy Settings\"\r\n```json\r\n{\r\n    \"displayName\": \"Consent Policy Settings\",\r\n    \"present\": true,\r\n    \"BlockUserConsentForRiskyApps\": true,\r\n    \"EnableAdminConsentRequests\": false\r\n}\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/directorySettings/example.md) for further information.\r\n\r\n### 2.6.17. OrganizationalBrandings\r\n\r\n##### Example for default organizational branding\r\n```json\r\n{\r\n    \"present\": true,\r\n    \"displayName\": \"default\",\r\n    \"backgroundColor\": \"#ffffff\",\r\n    \"customAccountResetCredentialsUrl\": \"Your custom URL\",\r\n    \"customCannotAccessYourAccountText\": \"Your custom text\",\r\n    \"customCannotAccessYourAccountUrl\": \"Your custom URL\",\r\n    \"customForgotMyPasswordText\": \"Your custom text\",\r\n    \"customPrivacyAndCookiesText\": \"Your custom text\",\r\n    \"customPrivacyAndCookiesUrl\": \"Your custom URL\",\r\n    \"customResetItNowText\": \"Your custom text\",\r\n    \"customTermsOfUseText\": \"Your custom text\",\r\n    \"customTermsOfUseUrl\": \"Your custom URL\",\r\n    \"headerBackgroundColor\": \"#000000\",\r\n    \"signInPageText\": \"Your custom text\",\r\n    \"usernameHintText\": \"Your custom text\"\r\n}\r\n```\r\n#### Example for localized organizational branding\r\n```json\r\n{\r\n    \"present\": true,\r\n    \"displayName\": \"en-US\",\r\n    \"backgroundColor\": \"#ffffff\",\r\n    \"signInPageText\": \"Another custom sign in text\",\r\n    \"usernameHintText\": \"Another custom username hint text\"\r\n}\r\n```\r\n\r\nPlease check the [.... example.md](./TMF/internal/data/configuration/organizationalBrandings/example.md) for further information.\r\n\r\n### 2.6.18. String mapping\r\nString mappings can help you with parameterization of your TMF configurations.\r\n\r\nYou can create mappings between strings and the values they should be replaced with. Place the mappings in the *stringMappings.json* file in the *stringMappings* folder of your configuration.\r\n\r\n\r\n| Property    | Description                                                                                |\r\n|-------------|--------------------------------------------------------------------------------------------|\r\n| name        | The name of the replacement string. Only digits (0-9) and letters (a-z A-Z) are allowed.   |\r\n| replace     | The future value after replacing.                                                          |\r\n\r\n```json\r\n{\r\n    \"name\": \"GroupManagerName\",\r\n    \"replace\": \"group.manager@example.org\"\r\n}\r\n```\r\n\r\nCurrently not all resource properties are considered. All string properties on the first level are replaced. String mappings also work when resolving users (eg. group owners or members), groups (in CA policies), applications (in CA Policies), namedLocations (in CA policies), agreements (in CA policies), accessPackages, accessPackageCatalogs, accessPackageResources, accessPackageAssignmentPolicies.\r\n\r\n| Resource       | Supported properties                                                                       |\r\n|----------------|--------------------------------------------------------------------------------------------|\r\n| agreements     | displayName, userReacceptRequiredFrequency                                                 |\r\n| groups         | description, mailNickname, members, owners                                                 |\r\n| namedLocations | displayName                                                                                |\r\n\r\n\r\nTo use the string mapping in a configuration file, you need to mention it by the name you provided in curly braces. Example: *{{ GroupManagerName }}*\r\n\r\n```json\r\n{   \r\n    \"displayName\": \"Some group\",\r\n    \"description\": \"This is a security group. The group manager is {{ GroupManagerName }}\",\r\n    \"groupTypes\": [],        \r\n    \"securityEnabled\": true,\r\n    \"mailEnabled\": false,\r\n    \"mailNickname\": \"someGroupForMembers\",\r\n    \"members\": [\"max.mustermann@example.org\"],\r\n    \"owners\": [\"group.owner@example.org\"],\r\n    \"present\": true\r\n}\r\n```\r\n\r\n## 2.7. Examples\r\n### 2.7.1. Example: A Conditional Access policy set and the required groups\r\nFirst of all you need to create a new configuration using *New-TmfConfiguration*\r\n```powershell\r\nNew-TmfConfiguration -Name \"Simple Group Example\" -Author \"Mustermann, Max\" -Weight 50 -OutPath \"$env:USERPROFILE\\Desktop\\Simple_Group_Example\" -Force\r\n```\r\nAfter that you need to add the definition for the include group into your configuration. We will include this group into our Conditional Access Policy. Just place the definition it into the *groups/groups.json* file in your newly created configuration.\r\n\r\nThe *groups.json* should now look like that.\r\n```json\r\n[\r\n  {   \r\n      \"displayName\": \"Some group to include into Conditional Access\",\r\n      \"description\": \"This is a simple security group\", \r\n      \"securityEnabled\": true,\r\n      \"mailEnabled\": false,\r\n      \"mailNickname\": \"someGroupForConditionalAccess\",\r\n      \"present\": true\r\n  }\r\n]\r\n```\r\nThe same is possible for the exclude group. Just add an additional group definition.\r\n```json\r\n[\r\n  {   \r\n      \"displayName\": \"Some group to include into Conditional Access\",\r\n      \"description\": \"This is a simple security group\", \r\n      \"securityEnabled\": true,\r\n      \"mailEnabled\": false,\r\n      \"mailNickname\": \"someGroupIncludeConditionalAccess\",\r\n      \"present\": true\r\n  },\r\n  {   \r\n      \"displayName\": \"Some group to exclude from Conditional Access\",\r\n      \"description\": \"This is a simple security group\", \r\n      \"securityEnabled\": true,\r\n      \"mailEnabled\": false,\r\n      \"mailNickname\": \"someGroupExcludeConditionalAccess\",\r\n      \"present\": true\r\n  }\r\n]\r\n```\r\nThe required groups are now defined. Finally we can define our Conditional Access Policy. For this example we just want MFA required for all members of the group *Some group to include into Conditional Access*.\r\n\r\nYou can add the following example Conditional Access Policy definition to *conditionalAccessPolicies/policies.json*.\r\n\r\n```json\r\n{\r\n    \"displayName\" : \"An example Conditional Access Policy\",\r\n    \"excludeGroups\": [\"Some group to include into Conditional Access\"],\r\n    \"excludeGroups\": [\"Some group to exclude from Conditional Access\"],        \r\n    \"includeApplications\": [\"All\"],        \r\n    \"includeLocations\": [\"All\"],\r\n    \"clientAppTypes\": [\"browser\", \"mobileAppsAndDesktopClients\"],\r\n    \"includePlatforms\": [\"All\"],\r\n    \"grantControls\": {\r\n        \"builtInControls\": [\"mfa\"],\r\n        \"operator\": \"AND\"\r\n    },\r\n    \"state\" : \"enabled\",\r\n    \"present\" : true\r\n}\r\n```\r\n\r\nNow that all required resource are defined, we can invoke the required actions. Simply use *Invoke-TmfTenant* to do the actions directly or use *Test-TmfTenant* to only test the configuration without changing anything.\r\n\r\n```powershell\r\nInvoke-TmfTenant\r\n```\r\n\r\n## 2.8. Adding existing resources to your configuration\r\n### 2.8.1. Named Locations (ipRange)\r\n\r\n```powershell\r\nImport-Module TMF -DisableNameChecking\r\nConnect-MgGraph -Scopes (Get-TmfRequiredScope -NamedLocations)\r\n\r\n$namedLocations = (Invoke-MgGraphRequest -Method GET -Uri \"v1.0/identity/conditionalAccess/namedLocations/?`$filter=isof('microsoft.graph.ipNamedLocation')\").value | Select-Object @{n = \"displayName\"; e = {$_[\"displayName\"]}}, @{n = \"type\";e = {\"ipNamedLocation\"}}, @{n = \"ipRanges\";e = {$_[\"ipRanges\"]}}, @{n = \"isTrusted\";e = {$_[\"isTrusted\"]}}\r\nforeach ($location in $namedLocations) {\r\n    $ipRanges = @()\r\n    switch ($location.ipRanges.GetType().Name) {\r\n        \"Object[]\" {\r\n            $location.ipRanges | ForEach-Object {\r\n                $ipRanges += [PSCustomObject]@{\r\n                    \"@odata.type\" = $_[\"@odata.type\"]\r\n                    \"cidrAddress\" = $_[\"cidrAddress\"]\r\n                }\r\n            }\r\n         }\r\n        default {\r\n            $ipRanges += [PSCustomObject]@{\r\n                \"@odata.type\" = $location.ipRanges[\"@odata.type\"]\r\n                \"cidrAddress\" = $location.ipRanges[\"cidrAddress\"]\r\n            }\r\n        }\r\n    }\r\n    $location.ipRanges = $ipRanges\r\n}\r\n$namedLocations | ConvertTo-Json -Depth 6 | Out-File -FilePath \"namedLocations.json\" -Encoding UTF8\r\n```\r\n\r\n### 2.8.2. Conditional Access Policies\r\n```powershell\r\nImport-Module TMF -DisableNameChecking\r\nConnect-MgGraph -Scopes (Get-TmfRequiredScope -ConditionalAccessPolicies)\r\n\r\n$policies = (Invoke-MgGraphRequest -Method GET -Uri \"v1.0/identity/conditionalAccess/policies\").Value | Select-Object @{n = \"displayName\"; e = {$_[\"displayName\"]}}, @{n = \"conditions\"; e = {$_[\"conditions\"]}}, @{n = \"grantControls\"; e = {$_[\"grantControls\"]}}, @{n = \"state\"; e = {$_[\"state\"]}}\r\nforeach ($policy in $policies) {    \r\n    #region conditions properties to first level\r\n    foreach ($property in $policy.conditions.GetEnumerator()) {\r\n        if ($property.Value) {\r\n            switch ($property.Value.GetType().Name) {\r\n                \"Hashtable\" {\r\n                    foreach ($childProperty in $policy.conditions.$($property.Key).GetEnumerator()) {\r\n                        if ($childProperty.Value) {\r\n                            Add-Member -InputObject $policy -MemberType NoteProperty -Name $childProperty.Key -Value $childProperty.Value\r\n                        }\r\n                    }\r\n                }\r\n                default {\r\n                    Add-Member -InputObject $policy -MemberType NoteProperty -Name $property.Key -Value $property.Value\r\n                }\r\n            }                \r\n        }            \r\n    }   \r\n    #endregion\r\n}\r\n$policies | ConvertTo-Json -Depth 6 | Out-File -FilePath \"policies.json\"  -Encoding UTF8\r\n```\r\n\r\n### 2.8.3. Groups\r\n```powershell\r\nConnect-MgGraph -Scopes (Get-TmfRequiredScope -Groups)\r\nSelect-MgProfile -Name beta\r\n\r\n$groups = Get-MgGroup -Property id, displayName, description, groupTypes, securityEnabled, mailEnabled, visibility, mailNickname | Select-Object id, displayName, description, groupTypes, securityEnabled, mailEnabled, visibility, mailNickname\r\nforeach ($group in $groups) {\r\n    \u003c# Uncomment if you want to add the group members to your configuration.\r\n    $members = @(Get-MgGroupMember -GroupId $group.Id -Property userPrincipalName | Foreach-Object {$_.AdditionalProperties[\"userPrincipalName\"]})\r\n    if ($members) {\r\n        Add-Member -InputObject $group -MemberType NoteProperty -Name \"members\" -Value $members\r\n    } #\u003e\r\n\r\n    \u003c# Uncomment if you want to add the group owners to your configuration.\r\n    $owners = @(Get-MgGroupOwner -GroupId $group.Id -Property userPrincipalName | Foreach-Object {$_.AdditionalProperties[\"userPrincipalName\"]})\r\n    if ($owners) {\r\n        Add-Member -InputObject $group -MemberType NoteProperty -Name \"owners\" -Value $owners\r\n    } #\u003e\r\n\r\n    Add-Member -InputObject $group -MemberType NoteProperty -Name \"present\" -Value $true\r\n}\r\n$groups | ConvertTo-Json -Depth 6 | Out-File -FilePath \"groups.json\" -Encoding UTF8\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FATVWGS%2Ftenant-management-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FATVWGS%2Ftenant-management-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FATVWGS%2Ftenant-management-framework/lists"}