Hi, and thanks for your remarks.
Actually Least Privileged is applied in this scenario where the 'Storage Account Contributor' only has access to the storage account.
The user has no access to the App Service or Function App in the portal.
In this case one of the user-assigned managed identities had contributor permissions on the subscription.
The other user-assigned Managed Identity also had access to the Key Vault, which opens several other doors.
Custom Roles is actually something that should be avoided because they often bad documented and hard to maintain in large environments.
In general all Azure Roles should only be assigned via PIM but that requires a license.
You could go down the path in only using Azure AD groups, but this creates the risk that a User Administrator in the Azure could elevate its permissions to Owner or contributor etc.