d365collaborative / d365fo.tools

Tools used for Dynamics 365 Finance and Operations
MIT License
236 stars 97 forks source link

:sparkles: new cmdlet New-D365EntraIntegration #789

Closed FH-Inway closed 6 months ago

FH-Inway commented 7 months ago

Since November 15, 2023, new cloud hosted environments are no longer integrated with the Microsoft Entra (formerly Active Directory) of the tenant the environment is deployed for.

This blocks some functionality, most notably the import of users from Entra.

Microsoft has provided instructions to set up the integration to enable the blocked functionality again: https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/secure-developer-vm#external-integrations

This multi-step manual process is a good candidate for automation by a script. @oysbre has already provided such a script at https://github.com/oysbre/D365tools/blob/main/CHEauth.ps1 and has kindly agreed that we can reuse parts of it for a new d365fo.tools cmdlet.

FH-Inway commented 7 months ago

There is a first draft of the refactored script by @oysbre in https://github.com/FH-Inway/d365fo.tools/blob/789-new-d365entraintegration/d365fo.tools/functions/new-d365entraintegration.ps1.

I also added new functionality where an existing certificate can be used instead of creating a new one.

Still needs some work and testing, I'm currently waiting on an app registration to do that.

@oysbre The part with the NetworkService read access is a bit beyond my expertise. Is there some documentation or guide I can read up on? It seems to me that full access instead of just read access is given. I found some resources, but they use different variations from your script's logic and I'm not versed enough to evaluate the differences.

Splaxi commented 7 months ago

That is impressive work right there!

oysbre commented 7 months ago

There is a first draft of the refactored script by @oysbre in https://github.com/FH-Inway/d365fo.tools/blob/789-new-d365entraintegration/d365fo.tools/functions/new-d365entraintegration.ps1.

I also added new functionality where an existing certificate can be used instead of creating a new one.

Still needs some work and testing, I'm currently waiting on an app registration to do that.

@oysbre The part with the NetworkService read access is a bit beyond my expertise. Is there some documentation or guide I can read up on? It seems to me that full access instead of just read access is given. I found some resources, but they use different variations from your script's logic and I'm not versed enough to evaluate the differences.

Hi. You can use [system.enum]::getnames([System.Security.AccessControl.FileSystemRights]) to evaluate the different ACLs. More about these here: https://learn.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.filesystemrights I used FullControl since I already had that in my other scripts for POS/Retail/Commerce, but set it to "Read" if that is the minimum requirement. Access control entries (ACEs) are the individual rights inside an ACL. An ACE can also be called a FileSystemAccessRule. This is a .NET object that has five parameters: -Security identifier ($Username) -The right (Modify|Read|FullControl ++) -Inheritance settings (ContainerInherit,ObjectInherit), which force all folders and files underneath the folder to inherit its new permissions. -Propagation settings (None). This parameter means nothing will interfere with the inheritance settings. -Type (Allow). The rest of the ACL is "translating" the SID of the NETWORKSERVICE, since Microsoft names the systemaccounts based on OS language! Scary...

FH-Inway commented 6 months ago

@oysbre Thank you, that was helpful. I was able to verify that "Read" is indeed the minimum requirement and changed the script to that effect.

@ everyone: While I still have some ideas for improvements and our automated test are not yet satisfied, I think the current state should already be useful. The experience using the new cmdlet is expected to be like the following examples:

New certificate, single environment

New-D365EntraIntegration -ClientId e70cac82-6a7c-4f9e-a8b9-e707b961e986

This is the simplest case, enable the Entra integration for a single environment, without plans on reusing the created certificate on other environments. image

New certificate, multiple environments

$securePassword = Read-Host -Prompt "Enter password" -AsSecureString
New-D365EntraIntegration -ClientId e70cac82-6a7c-4f9e-a8b9-e707b961e986 -CertificatePassword $securePassword

This would be the case when enabling the Entra integration on the first of multiple environments. So in addition to the client id of the app registration, a password is needed to export the private key file of the certificate. image

Existing certificate

$securePassword = Read-Host -Prompt "Enter password" -AsSecureString
New-D365EntraIntegration -ClientId e70cac82-6a7c-4f9e-a8b9-e707b961e986 -CertificatePassword $securePassword -CertificatePassword $securePassword -ExistingCertificateFile C:\Temp\CHEAuth.cer -ExistingCertificatePrivateKeyFile C:\Temp\CHEAuth.pfx

This is how I expect the cmdlet will be most commonly called, with an existing certificate. Note in this case no message to upload the certificate to Azure is printed, because it is assumed that at this time, this is already done. image

FH-Inway commented 6 months ago

Alright, the automated test gods seem to be satisfied now. Sorry to everyone who got notification spammed, I created #794 a bit too early.

@Splaxi Over to you.

Splaxi commented 6 months ago

@FH-Inway

Sorry - but not really sorry - for the tests to be somewhat persistent 😉

I'm really in AWE over the effort put into this one - solid work - like always!

Splaxi commented 6 months ago

0.7.7 - is being released.

FH-Inway commented 6 months ago

Sorry - but not really sorry - for the tests to be somewhat persistent 😉

As they should be :)

Thanks for the merge and release, I was able to test it "in the wild", looks good so far. Let's see what the rest (i.e. Yammer) has to say.

oysbre commented 6 months ago

Sorry - but not really sorry - for the tests to be somewhat persistent 😉

As they should be :)

Thanks for the merge and release, I was able to test it "in the wild", looks good so far. Let's see what the rest (i.e. Yammer) has to say.

Tested the function, but it didn't give NETWORKSERVICE read rights to the certificate. Theres is a check for Environmenttype? Think it skipped that on my new CHE.

FH-Inway commented 6 months ago

Tested the function, but it didn't give NETWORKSERVICE read rights to the certificate. Theres is a check for Environmenttype? Think it skipped that on my new CHE.

Interesting. Could you run the following script and compare the HostName value with the following logic in variables.ps1? The NETWORKSERVICE read rights are set if environment type is AzureHostedTier1.

$environment = Get-D365EnvironmentSettings
$environment.Infrastructure.HostName

https://github.com/d365collaborative/d365fo.tools/blob/e8c0cca211376c70054e76e7c81b53b746a664aa/d365fo.tools/internal/scripts/variables.ps1#L64-L78

FH-Inway commented 6 months ago

I've been playing around with the idea mentioned in https://www.yammer.com/dynamicsaxfeedbackprograms/threads/2535916690333696 of using an Azure key vault to store the certificate.

This resulted so far in the following script that downloads a certificate from a key vault and stores it as .pfx and .cer file, ready for consumption by New-D365EntraIntegration: https://gist.github.com/FH-Inway/86507ac3ed3e9b2e645ca015b9634f9a

The user running the script needs at least secret get access policy on the key vault (see https://learn.microsoft.com/en-us/azure/key-vault/general/assign-access-policy).

Splaxi commented 6 months ago

But wouldn't that make sense to keep out of the tools.

But a wiki, that shows how to utilize the standard module for KeyVault, downloading the secret - and then use the tools, would make more sense.

FH-Inway commented 6 months ago

Agreed. I don't want to make d365fo.tools a wrapper around the Az module :)

But yeah, a wiki tutorial or how-to would make sense, hadn't thought that far ahead yet. Currently also playing around with Bicep, so maybe a deployment template for a key vault with certificate to go along with it. Just need to find the time...

Splaxi commented 6 months ago

I can supply all key Vault bicep you need....

FH-Inway commented 6 months ago

Sent you an invite to a repo.

oysbre commented 6 months ago
$environment = Get-D365EnvironmentSettings
$environment.Infrastructure.HostName

@FH-Inway Ran the script, and as you can see it's called "axcloud" and not "cloudax" as referenced in your Env check. can you add-or ($environment.Infrastructure.HostName -like "*axcloud.*dynamics.com*") . CHE is deployed to Norway East. servername.axcloud.dynamics.com Don't know why MS use different FQDN. Different image perhaps in regions. There is a yammer article that also reference this using app registrations https://www.yammer.com/dynamicsaxfeedbackprograms/#/Threads/show?threadId=1395632590667776&search_origin=global&scoring=linear1Y-prankie-group-private-higher&match=any-exact&search_sort=relevance&page=1&search=axcloud%20cloudax

FH-Inway commented 6 months ago

@oysbre Thanks. Curious that is still happening. I added a regex, see https://github.com/d365collaborative/d365fo.tools/pull/798/files#diff-d8038e83990314f92311ff3cbe611afd89f3b7f91d7d345a3a87a4ccdecbeb1fR68