From 6809e944f9a993eb8f313ed68686482316615125 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Mon, 16 Jun 2025 17:05:00 +0300 Subject: [PATCH 01/10] Add validations --- validations/Validate.ps1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 validations/Validate.ps1 diff --git a/validations/Validate.ps1 b/validations/Validate.ps1 new file mode 100644 index 0000000000..e69de29bb2 From 1d34e44cdb9a464c481476fb558042081d02bae8 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Thu, 17 Jul 2025 12:36:07 +0300 Subject: [PATCH 02/10] Add validations --- validations/Entra-ModuleMapping.json | 261 +++++++++++++++++++ validations/EntraBeta-ModuleMapping.json | 311 +++++++++++++++++++++++ validations/Validate-EntraModule.ps1 | 16 ++ validations/Validator.ps1 | 75 ++++++ 4 files changed, 663 insertions(+) create mode 100644 validations/Entra-ModuleMapping.json create mode 100644 validations/EntraBeta-ModuleMapping.json create mode 100644 validations/Validate-EntraModule.ps1 create mode 100644 validations/Validator.ps1 diff --git a/validations/Entra-ModuleMapping.json b/validations/Entra-ModuleMapping.json new file mode 100644 index 0000000000..0402cc38a8 --- /dev/null +++ b/validations/Entra-ModuleMapping.json @@ -0,0 +1,261 @@ +{ + "Get-EntraApplication": "Applications", + "Get-EntraDeletedDirectoryObject": "DirectoryManagement", + "New-EntraGroupAppRoleAssignment": "Groups", + "Get-EntraApplicationPasswordCredential": "Applications", + "Get-EntraUserCBAAuthorizationInfo": "CertificateBasedAuthentication", + "Add-EntraGroupOwner": "Groups", + "Remove-EntraDeletedApplication": "Applications", + "New-EntraNamedLocationPolicy": "SignIns", + "Set-EntraPolicy": "SignIns", + "Add-EntraScopedRoleMembership": "DirectoryManagement", + "Find-EntraPermission": "Authentication", + "New-EntraInvitation": "SignIns", + "Get-EntraAuthenticationMethodUserRegistrationDetailReport": "Reports", + "Get-EntraDirSyncFeature": "DirectoryManagement", + "Remove-EntraDevice": "DirectoryManagement", + "Remove-EntraAdministrativeUnitMember": "DirectoryManagement", + "New-EntraGroup": "Groups", + "Get-EntraAttributeSet": "DirectoryManagement", + "Set-EntraAuthorizationPolicy": "SignIns", + "Get-EntraPermissionGrantConditionSet": "SignIns", + "Set-EntraNamedLocationPolicy": "SignIns", + "Add-EntraLifecyclePolicyGroup": "Groups", + "Add-EntraDeviceRegisteredOwner": "DirectoryManagement", + "Update-EntraOauth2PermissionGrant": "SignIns", + "Get-EntraDeletedGroup": "Groups", + "Set-EntraApplication": "Applications", + "Get-EntraUserAppRoleAssignment": "Users", + "Get-EntraDirectoryRole": "DirectoryManagement", + "Get-EntraScopedRoleMembership": "DirectoryManagement", + "New-EntraGroupLifecyclePolicy": "Groups", + "New-EntraApplicationKeyCredential": "Applications", + "Remove-EntraUserManager": "Users", + "Add-EntraDirectoryRoleMember": "DirectoryManagement", + "Get-EntraSubscribedSku": "DirectoryManagement", + "Get-EntraAccountSku": "DirectoryManagement", + "Get-EntraServicePrincipalDelegatedPermissionClassification": "Applications", + "New-EntraIdentityProvider": "SignIns", + "Get-EntraExtensionProperty": "DirectoryManagement", + "Remove-EntraGroupLifecyclePolicy": "Groups", + "Set-EntraDirSyncEnabled": "DirectoryManagement", + "Revoke-EntraSignedInUserAllRefreshToken": "Authentication", + "Remove-EntraPermissionGrantConditionSet": "SignIns", + "Remove-EntraDeletedDirectoryObject": "DirectoryManagement", + "Get-EntraUserAdministrativeUnit": "Users", + "Set-EntraTenantDetail": "DirectoryManagement", + "Set-EntraDevice": "DirectoryManagement", + "Reset-EntraLifeCycleGroup": "Groups", + "Remove-EntraApplicationOwner": "Applications", + "Remove-EntraApplicationExtensionProperty": "Applications", + "Get-EntraServicePrincipalCreatedObject": "Applications", + "Remove-EntraNamedLocationPolicy": "SignIns", + "Remove-EntraGroupMember": "Groups", + "Get-EntraServicePrincipalKeyCredential": "Applications", + "Get-EntraDeviceRegisteredUser": "DirectoryManagement", + "Remove-EntraServicePrincipalDelegatedPermissionClassification": "Applications", + "Get-EntraUserAuthenticationMethod": "SignIns", + "Add-EntraServicePrincipalOwner": "Applications", + "Add-EntraDeviceRegisteredUser": "DirectoryManagement", + "Enable-EntraDirectoryRole": "DirectoryManagement", + "Set-EntraDomainFederationSettings": "DirectoryManagement", + "Get-EntraUserManager": "Users", + "Remove-EntraServicePrincipalOwner": "Applications", + "Remove-EntraTrustedCertificateAuthority": "SignIns", + "New-EntraPolicy": "SignIns", + "Get-EntraAdministrativeUnit": "DirectoryManagement", + "Set-EntraUserPassword": "Users", + "New-EntraDirectoryRoleAssignment": "Governance", + "New-EntraPermissionGrantPolicy": "SignIns", + "New-EntraServicePrincipalPasswordCredential": "Applications", + "Connect-Entra": "Authentication", + "Add-EntraGroupMember": "Groups", + "Disconnect-Entra": "Authentication", + "New-EntraApplicationFromApplicationTemplate": "Applications", + "Get-EntraFeatureRolloutPolicy": "SignIns", + "Get-EntraIdentityProvider": "SignIns", + "New-EntraAdministrativeUnit": "DirectoryManagement", + "Remove-EntraGroupOwner": "Groups", + "Get-EntraGroupPermissionGrant": "Groups", + "Get-EntraDomainNameReference": "DirectoryManagement", + "Get-EntraServicePrincipal": "Applications", + "Get-EntraAuditSignInLog": "Reports", + "Select-EntraGroupIdsContactIsMemberOf": "Groups", + "Set-EntraCustomSecurityAttributeDefinition": "DirectoryManagement", + "Select-EntraGroupIdsGroupIsMemberOf": "Groups", + "Set-EntraGroupLifecyclePolicy": "Groups", + "Remove-EntraDirectoryRoleDefinition": "Governance", + "Remove-EntraApplicationKey": "Applications", + "Get-EntraCustomSecurityAttributeDefinition": "DirectoryManagement", + "Remove-EntraConditionalAccessPolicy": "SignIns", + "Get-EntraDeletedAdministrativeUnit": "DirectoryManagement", + "Get-EntraGroup": "Groups", + "New-EntraServicePrincipalAppRoleAssignment": "Applications", + "Get-EntraUserDirectReport": "Users", + "Get-EntraDirectoryObject": "DirectoryManagement", + "Get-EntraPartnerInformation": "DirectoryManagement", + "Get-EntraTenantDetail": "DirectoryManagement", + "Confirm-EntraDomain": "DirectoryManagement", + "Get-EntraDeviceRegisteredOwner": "DirectoryManagement", + "Remove-EntraApplicationPasswordCredential": "Applications", + "Add-EntraEnvironment": "Authentication", + "Restore-EntraDeletedApplication": "Applications", + "Set-EntraUserExtension": "Users", + "New-EntraApplicationPasswordCredential": "Applications", + "Get-EntraContactThumbnailPhoto": "DirectoryManagement", + "Set-EntraDomain": "DirectoryManagement", + "New-EntraApplicationPassword": "Applications", + "New-EntraFeatureRolloutPolicy": "SignIns", + "New-EntraTrustedCertificateAuthority": "SignIns", + "New-EntraUserAppRoleAssignment": "Users", + "Get-EntraApplicationTemplate": "Applications", + "Set-EntraFeatureRolloutPolicy": "SignIns", + "Add-EntraAdministrativeUnitMember": "DirectoryManagement", + "Get-EntraDirectoryRoleDefinition": "Governance", + "Get-EntraDeletedUser": "Users", + "New-EntraApplicationExtensionProperty": "Applications", + "Remove-EntraFeatureRolloutPolicyDirectoryObject": "SignIns", + "Get-EntraFederationProperty": "DirectoryManagement", + "Remove-EntraDomain": "DirectoryManagement", + "Reset-EntraStrongAuthenticationMethodByUpn": "SignIns", + "Get-EntraGroupMember": "Groups", + "Remove-EntraApplication": "Applications", + "Get-EntraServicePrincipalOwner": "Applications", + "Set-EntraServicePrincipal": "Applications", + "Get-EntraUserOAuth2PermissionGrant": "Users", + "Get-EntraObjectSetting": "Groups", + "Set-EntraUserManager": "Users", + "Get-EntraApplicationKeyCredential": "Applications", + "New-EntraDomain": "DirectoryManagement", + "New-EntraApplicationKey": "Applications", + "Get-EntraTrustedCertificateAuthority": "SignIns", + "Get-CrossCloudVerificationCode": "DirectoryManagement", + "Update-EntraUserFromFederated": "Users", + "Set-EntraGroup": "Groups", + "Remove-EntraPermissionGrantPolicy": "SignIns", + "Set-EntraConditionalAccessPolicy": "SignIns", + "Get-EntraServicePrincipalOAuth2PermissionGrant": "Applications", + "Get-EntraContract": "DirectoryManagement", + "Remove-EntraServicePrincipalAppRoleAssignment": "Applications", + "Get-EntraPasswordPolicy": "DirectoryManagement", + "New-EntraUser": "Users", + "Get-EntraDomainFederationSettings": "DirectoryManagement", + "Get-EntraDirectoryRoleMember": "DirectoryManagement", + "Set-EntraUserSponsor": "Users", + "Set-EntraUser": "Users", + "Get-EntraServicePrincipalPasswordCredential": "Applications", + "Get-EntraUserInactiveSignIn": "Users", + "Set-EntraAdministrativeUnit": "DirectoryManagement", + "Remove-EntraGroupAppRoleAssignment": "Groups", + "New-EntraApplication": "Applications", + "Restore-EntraDeletedDirectoryObject": "DirectoryManagement", + "Remove-EntraDeviceRegisteredUser": "DirectoryManagement", + "Update-EntraSignedInUserPassword": "Users", + "Set-EntraPermissionGrantConditionSet": "SignIns", + "Add-EntraServicePrincipalDelegatedPermissionClassification": "Applications", + "Get-EntraPolicy": "SignIns", + "New-EntraConditionalAccessPolicy": "SignIns", + "Get-EntraDirectoryObjectOnPremisesProvisioningError": "DirectoryManagement", + "Set-EntraPermissionGrantPolicy": "SignIns", + "Get-EntraDeletedDevice": "DirectoryManagement", + "Remove-EntraApplicationKeyCredential": "Applications", + "Set-EntraDirSyncFeature": "DirectoryManagement", + "Remove-EntraPolicy": "SignIns", + "Remove-EntraDeviceRegisteredOwner": "DirectoryManagement", + "Set-EntraUserLicense": "Users", + "Select-EntraGroupIdsServicePrincipalIsMemberOf": "Applications", + "Get-EntraGroupOwner": "Groups", + "Remove-EntraUser": "Users", + "Get-EntraPermissionGrantPolicy": "SignIns", + "Remove-EntraUserExtension": "Users", + "Remove-EntraApplicationVerifiedPublisher": "Applications", + "Set-EntraCustomSecurityAttributeDefinitionAllowedValue": "DirectoryManagement", + "Remove-EntraServicePrincipal": "Applications", + "Get-EntraContactDirectReport": "DirectoryManagement", + "Get-EntraUserOwnedObject": "Users", + "New-EntraOauth2PermissionGrant": "SignIns", + "Get-EntraGroupAppRoleAssignment": "Groups", + "New-EntraServicePrincipalKeyCredential": "Applications", + "Remove-EntraDirectoryRoleMember": "DirectoryManagement", + "Get-EntraUserRegisteredDevice": "Users", + "Get-EntraCustomSecurityAttributeDefinitionAllowedValue": "DirectoryManagement", + "Get-EntraUserSponsor": "Users", + "New-EntraServicePrincipal": "Applications", + "Get-EntraNamedLocationPolicy": "SignIns", + "Get-EntraContactMembership": "DirectoryManagement", + "Get-EntraAuditDirectoryLog": "Reports", + "Add-EntraCustomSecurityAttributeDefinitionAllowedValue": "DirectoryManagement", + "Get-EntraDirectoryRoleTemplate": "DirectoryManagement", + "Set-EntraUserCBACertificateUserId": "CertificateBasedAuthentication", + "Remove-EntraUserAppRoleAssignment": "Users", + "Get-EntraAdministrativeUnitMember": "DirectoryManagement", + "Get-EntraUserGroup": "Users", + "Set-EntraApplicationLogo": "Applications", + "Remove-EntraContact": "DirectoryManagement", + "Get-EntraDomainServiceConfigurationRecord": "DirectoryManagement", + "Get-EntraUserExtension": "Users", + "Remove-EntraDirectoryRoleAssignment": "Governance", + "Get-EntraServicePrincipalAppRoleAssignedTo": "Applications", + "Get-EntraUserCertificateUserIdsFromCertificate": "CertificateBasedAuthentication", + "Set-EntraDirectoryRoleDefinition": "Governance", + "Get-EntraUserMembership": "Users", + "Get-EntraAuthorizationPolicy": "SignIns", + "Get-EntraUserCreatedObject": "Users", + "Set-EntraUserThumbnailPhoto": "Users", + "Get-EntraContact": "DirectoryManagement", + "Revoke-EntraUserAllRefreshToken": "Authentication", + "Get-EntraServicePrincipalMembership": "Applications", + "Get-EntraUserThumbnailPhoto": "Users", + "Get-EntraUserRole": "Users", + "New-EntraDevice": "DirectoryManagement", + "Get-EntraContext": "Authentication", + "Remove-EntraUserSponsor": "Users", + "Set-EntraDirSyncConfiguration": "DirectoryManagement", + "Set-EntraAttributeSet": "DirectoryManagement", + "Set-EntraIdentityProvider": "SignIns", + "Remove-EntraAdministrativeUnit": "DirectoryManagement", + "Remove-EntraGroup": "Groups", + "Get-EntraDevice": "DirectoryManagement", + "Select-EntraGroupIdsUserIsMemberOf": "Groups", + "Set-EntraApplicationVerifiedPublisher": "Applications", + "Set-EntraTrustedCertificateAuthority": "SignIns", + "New-EntraCustomSecurityAttributeDefinition": "DirectoryManagement", + "Get-EntraUser": "Users", + "Get-EntraDeletedApplication": "Applications", + "Get-EntraContactManager": "DirectoryManagement", + "Remove-EntraExternalDomainFederation": "DirectoryManagement", + "Get-EntraApplicationExtensionProperty": "Applications", + "Get-EntraDomain": "DirectoryManagement", + "Resolve-EntraTenant": "DirectoryManagement", + "Get-EntraServicePrincipalAppRoleAssignment": "Applications", + "Remove-EntraScopedRoleMembership": "DirectoryManagement", + "Get-EntraApplicationOwner": "Applications", + "Remove-EntraServicePrincipalPasswordCredential": "Applications", + "Set-EntraPartnerInformation": "DirectoryManagement", + "Get-EntraInactiveSignInUser": "Users", + "Get-EntraServicePrincipalOwnedObject": "Applications", + "Get-EntraDirectoryRoleAssignment": "Governance", + "Get-EntraUserOwnedDevice": "Users", + "Get-EntraConditionalAccessPolicy": "SignIns", + "New-EntraDirectoryRoleDefinition": "Governance", + "Remove-EntraIdentityProvider": "SignIns", + "Get-EntraApplicationLogo": "Applications", + "Get-EntraGroupLifecyclePolicy": "Groups", + "Add-EntraApplicationOwner": "Applications", + "Get-EntraDeletedServicePrincipal": "Applications", + "Get-EntraSubscription": "DirectoryManagement", + "Get-EntraOAuth2PermissionGrant": "SignIns", + "Get-EntraUserLicenseDetail": "Users", + "Get-EntraDomainVerificationDnsRecord": "DirectoryManagement", + "Get-EntraEnvironment": "Authentication", + "Remove-EntraOAuth2PermissionGrant": "SignIns", + "New-EntraAttributeSet": "DirectoryManagement", + "Get-EntraApplicationServiceEndpoint": "Applications", + "New-EntraPermissionGrantConditionSet": "SignIns", + "Get-EntraDirSyncConfiguration": "DirectoryManagement", + "Get-EntraLifecyclePolicyGroup": "Groups", + "Remove-EntraApplicationPassword": "Applications", + "Remove-EntraLifecyclePolicyGroup": "Groups", + "Remove-EntraServicePrincipalKeyCredential": "Applications", + "Remove-EntraFeatureRolloutPolicy": "SignIns" +} diff --git a/validations/EntraBeta-ModuleMapping.json b/validations/EntraBeta-ModuleMapping.json new file mode 100644 index 0000000000..490443581e --- /dev/null +++ b/validations/EntraBeta-ModuleMapping.json @@ -0,0 +1,311 @@ +{ + "Connect-Entra": "Authentication", + "Remove-EntraBetaUser": "Users", + "Get-EntraBetaAuthorizationPolicy": "SignIns", + "Get-EntraBetaDirectoryRoleDefinition": "Governance", + "Set-EntraBetaPermissionGrantConditionSet": "SignIns", + "New-EntraBetaTrustedCertificateAuthority": "SignIns", + "Get-EntraBetaGroup": "Groups", + "Set-EntraBetaGroupLifecyclePolicy": "Groups", + "New-EntraBetaIdentityProvider": "SignIns", + "Get-EntraBetaApplicationServiceEndpoint": "Applications", + "Get-EntraBetaSubscription": "DirectoryManagement", + "Get-EntraBetaServicePrincipalCreatedObject": "Applications", + "Remove-EntraBetaApplicationKey": "Applications", + "Remove-EntraBetaScopedRoleMembership": "DirectoryManagement", + "Get-EntraBetaServicePrincipalOwner": "Applications", + "Set-EntraBetaFeatureRolloutPolicy": "SignIns", + "Get-EntraBetaApplicationKeyCredential": "Applications", + "New-EntraBetaAdministrativeUnit": "DirectoryManagement", + "Get-EntraBetaDomainFederationSettings": "DirectoryManagement", + "Enable-EntraBetaDirectoryRole": "DirectoryManagement", + "Remove-EntraBetaUserSponsor": "Users", + "Select-EntraBetaGroupIdsGroupIsMemberOf": "Groups", + "Set-EntraBetaUserPassword": "Users", + "Get-EntraBetaApplicationProxyConnectorGroupMembers": "Applications", + "Get-EntraBetaTrustFrameworkPolicy": "SignIns", + "Get-EntraBetaDomainVerificationDnsRecord": "DirectoryManagement", + "Get-EntraBetaAuditDirectoryLog": "Reports", + "Set-EntraBetaAttributeSet": "DirectoryManagement", + "Get-EntraBetaUserManager": "Users", + "Get-EntraBetaUserSponsor": "Users", + "New-EntraBetaUser": "Users", + "Get-EntraBetaPolicy": "SignIns", + "Remove-EntraBetaPrivateAccessApplicationSegment": "NetworkAccess", + "Get-EntraBetaUserExtension": "Users", + "Set-EntraBetaObjectSetting": "Groups", + "Get-EntraBetaServicePrincipalDelegatedPermissionClassification": "Applications", + "Select-EntraBetaGroupIdsContactIsMemberOf": "Groups", + "Set-EntraBetaPasswordSingleSignOnCredential": "Applications", + "Set-EntraBetaPartnerInformation": "DirectoryManagement", + "Remove-EntraBetaApplicationVerifiedPublisher": "Applications", + "Confirm-EntraBetaDomain": "DirectoryManagement", + "Get-EntraBetaApplicationLogo": "Applications", + "Get-EntraBetaAttributeSet": "DirectoryManagement", + "Get-EntraBetaApplicationPasswordCredential": "Applications", + "New-EntraBetaGroupLifecyclePolicy": "Groups", + "Remove-EntraBetaApplicationPasswordCredential": "Applications", + "Add-EntraBetaLifecyclePolicyGroup": "Groups", + "New-EntraBetaNamedLocationPolicy": "SignIns", + "Get-EntraBetaPrivilegedRoleSetting": "Governance", + "New-EntraBetaPolicy": "SignIns", + "Add-EntraBetaApplicationPolicy": "Applications", + "Get-EntraBetaDeviceRegisteredOwner": "DirectoryManagement", + "New-EntraBetaPrivateAccessApplication": "NetworkAccess", + "Get-EntraBetaDirectoryRoleTemplate": "DirectoryManagement", + "Get-EntraBetaApplicationExtensionProperty": "Applications", + "Get-EntraBetaApplicationSignInDetailedSummary": "Reports", + "Get-EntraBetaUserRegisteredDevice": "Users", + "Remove-EntraBetaPermissionGrantPolicy": "SignIns", + "New-EntraBetaPrivateAccessApplicationSegment": "NetworkAccess", + "New-EntraBetaApplication": "Applications", + "Set-EntraBetaDevice": "DirectoryManagement", + "Remove-EntraBetaAdministrativeUnit": "DirectoryManagement", + "New-EntraBetaPasswordSingleSignOnCredential": "Applications", + "New-EntraBetaAdministrativeUnitMember": "DirectoryManagement", + "New-EntraBetaApplicationProxyConnectorGroup": "Applications", + "Get-EntraBetaUserGroup": "Users", + "Add-EntraBetaServicePrincipalPolicy": "SignIns", + "Remove-EntraBetaDeletedDirectoryObject": "DirectoryManagement", + "Remove-EntraBetaFeatureRolloutPolicyDirectoryObject": "SignIns", + "Get-EntraBetaUserLicenseDetail": "Users", + "Set-EntraBetaApplicationVerifiedPublisher": "Applications", + "Remove-EntraBetaServicePrincipalAppRoleAssignment": "Applications", + "Get-EntraBetaAdministrativeUnitMember": "DirectoryManagement", + "Get-EntraBetaTenantDetail": "DirectoryManagement", + "Remove-EntraBetaContact": "DirectoryManagement", + "Remove-EntraBetaGroupAppRoleAssignment": "Groups", + "Set-EntraBetaPrivilegedRoleAssignmentRequest": "Governance", + "Set-EntraBetaDirectorySetting": "DirectoryManagement", + "Get-EntraBetaUserAppRoleAssignment": "Users", + "Remove-EntraBetaOAuth2PermissionGrant": "SignIns", + "Remove-EntraBetaServicePrincipalPolicy": "SignIns", + "New-EntraBetaCustomSecurityAttributeDefinition": "DirectoryManagement", + "Remove-EntraBetaGroup": "Groups", + "Remove-EntraBetaApplicationPolicy": "Applications", + "Remove-EntraBetaTrustFrameworkPolicy": "SignIns", + "New-EntraBetaApplicationKey": "Applications", + "Get-EntraBetaServicePrincipal": "Applications", + "Set-EntraBetaUserSponsor": "Users", + "Set-EntraBetaUserManager": "Users", + "Remove-EntraBetaAdministrativeUnitMember": "DirectoryManagement", + "Add-EntraBetaFeatureRolloutPolicyDirectoryObject": "SignIns", + "Set-EntraBetaUserThumbnailPhoto": "Users", + "Get-EntraBetaLifecyclePolicyGroup": "Groups", + "Get-EntraBetaGlobalSecureAccessTenantStatus": "NetworkAccess", + "Get-EntraBetaUserOwnedObject": "Users", + "Remove-EntraBetaIdentityProvider": "SignIns", + "Remove-EntraBetaConditionalAccessPolicy": "SignIns", + "Set-EntraBetaIdentityProvider": "SignIns", + "Enable-EntraBetaGlobalSecureAccessTenant": "NetworkAccess", + "Set-EntraBetaUser": "Users", + "Set-EntraBetaDirSyncFeature": "DirectoryManagement", + "Remove-EntraBetaDirectorySetting": "DirectoryManagement", + "New-EntraBetaServicePrincipal": "Applications", + "Get-EntraBetaUserInactiveSignIn": "Users", + "Remove-EntraBetaDirectoryRoleDefinition": "Governance", + "Add-EntraBetaAdministrativeUnitMember": "DirectoryManagement", + "Remove-EntraBetaApplicationProxyConnectorGroup": "Applications", + "Set-EntraBetaApplicationProxyApplicationSingleSignOn": "Applications", + "Add-EntraBetaServicePrincipalDelegatedPermissionClassification": "Applications", + "Get-EntraBetaPrivilegedRoleDefinition": "Governance", + "New-EntraBetaObjectSetting": "Groups", + "Get-EntraBetaApplication": "Applications", + "Select-EntraBetaGroupIdsUserIsMemberOf": "Groups", + "Remove-EntraBetaServicePrincipal": "Applications", + "Remove-EntraBetaGroupMember": "Groups", + "Get-EntraBetaAdministrativeUnit": "DirectoryManagement", + "Get-EntraBetaAuthenticationMethodUserRegistrationDetailReport": "Reports", + "Select-EntraBetaGroupIdsServicePrincipalIsMemberOf": "Applications", + "Remove-EntraBetaApplicationPassword": "Applications", + "Get-EntraBetaGroupAppRoleAssignment": "Groups", + "Get-EntraBetaDirSyncConfiguration": "DirectoryManagement", + "Get-EntraBetaObjectSetting": "Groups", + "Get-EntraBetaOAuth2PermissionGrant": "SignIns", + "Get-EntraBetaUser": "Users", + "Get-EntraBetaPolicyAppliedObject": "SignIns", + "New-EntraBetaInvitation": "SignIns", + "Get-EntraBetaApplicationProxyConnectorMemberOf": "Applications", + "Remove-EntraBetaFeatureRolloutPolicy": "SignIns", + "New-EntraBetaDirectoryRoleDefinition": "Governance", + "Get-EntraBetaFederationProperty": "DirectoryManagement", + "Get-EntraBetaDirSyncFeature": "DirectoryManagement", + "Get-EntraBetaDeletedApplication": "Applications", + "Get-EntraBetaDirectorySetting": "DirectoryManagement", + "Get-EntraBetaDeletedUser": "Users", + "Get-EntraBetaPasswordSingleSignOnCredential": "Applications", + "Add-EntraBetaDirectoryRoleMember": "DirectoryManagement", + "New-EntraBetaTrustFrameworkPolicy": "SignIns", + "Add-EntraBetaGroupMember": "Groups", + "Set-EntraBetaApplication": "Applications", + "Set-EntraBetaApplicationProxyConnector": "Applications", + "Get-EntraBetaApplicationPolicy": "Applications", + "Remove-EntraBetaDirectoryRoleMember": "DirectoryManagement", + "Set-EntraBetaApplicationProxyConnectorGroup": "Applications", + "Get-EntraBetaServicePrincipalOwnedObject": "Applications", + "Set-EntraBetaTenantDetail": "DirectoryManagement", + "Add-EntraBetaGroupOwner": "Groups", + "Get-EntraBetaNamedLocationPolicy": "SignIns", + "New-EntraBetaApplicationKeyCredential": "Applications", + "New-EntraBetaApplicationFromApplicationTemplate": "Applications", + "Get-EntraBetaPermissionGrantPolicy": "SignIns", + "Get-EntraBetaServicePrincipalMembership": "Applications", + "Get-EntraBetaDirectoryRoleAssignment": "Governance", + "New-EntraBetaPermissionGrantConditionSet": "SignIns", + "Add-EntraBetaScopedRoleMembership": "DirectoryManagement", + "Add-EntraBetaDeviceRegisteredOwner": "DirectoryManagement", + "Restore-EntraBetaDeletedDirectoryObject": "DirectoryManagement", + "New-EntraBetaServicePrincipalPasswordCredential": "Applications", + "Update-EntraBetaOauth2PermissionGrant": "SignIns", + "Get-EntraBetaContactDirectReport": "DirectoryManagement", + "Set-EntraBetaUserExtension": "Users", + "Get-EntraBetaPrivateAccessApplication": "NetworkAccess", + "Remove-EntraBetaDomain": "DirectoryManagement", + "Remove-EntraBetaDeviceRegisteredUser": "DirectoryManagement", + "Set-EntraBetaServicePrincipal": "Applications", + "New-EntraBetaDomain": "DirectoryManagement", + "Get-EntraBetaServicePrincipalOAuth2PermissionGrant": "Applications", + "Set-EntraBetaDirectoryRoleDefinition": "Governance", + "Get-EntraBetaDomainNameReference": "DirectoryManagement", + "Get-EntraBetaCustomSecurityAttributeDefinition": "DirectoryManagement", + "Get-EntraBetaDomainServiceConfigurationRecord": "DirectoryManagement", + "Update-EntraBetaSignedInUserPassword": "Users", + "Get-EntraBetaDirectoryObject": "DirectoryManagement", + "Revoke-EntraBetaUserAllRefreshToken": "Authentication", + "Set-EntraBetaTrustFrameworkPolicy": "SignIns", + "Get-EntraBetaUserRole": "Users", + "Get-EntraBetaApplicationProxyConnectorGroup": "Applications", + "Remove-EntraBetaUserManager": "Users", + "Remove-EntraBetaServicePrincipalOwner": "Applications", + "Remove-EntraBetaApplicationProxyApplication": "Applications", + "Get-EntraBetaContract": "DirectoryManagement", + "Set-EntraBetaAdministrativeUnit": "DirectoryManagement", + "Remove-EntraBetaApplication": "Applications", + "Get-EntraBetaApplicationProxyApplication": "Applications", + "Remove-EntraBetaTrustedCertificateAuthority": "SignIns", + "Remove-EntraBetaApplicationKeyCredential": "Applications", + "Get-EntraBetaPrivilegedResource": "Governance", + "Get-EntraBetaPrivilegedRole": "Governance", + "Get-EntraBetaServicePrincipalAppRoleAssignedTo": "Applications", + "Set-EntraBetaAuthorizationPolicy": "SignIns", + "Get-EntraBetaUserCreatedObject": "Users", + "Reset-EntraBetaStrongAuthenticationMethodByUpn": "SignIns", + "Get-EntraBetaApplicationTemplate": "Applications", + "New-EntraBetaDirectorySetting": "DirectoryManagement", + "Add-EntraBetaCustomSecurityAttributeDefinitionAllowedValue": "DirectoryManagement", + "Get-EntraBetaSubscribedSku": "DirectoryManagement", + "Get-EntraBetaAuditSignInLog": "Reports", + "New-EntraBetaPrivilegedRoleAssignment": "Governance", + "Remove-EntraBetaApplicationProxyApplicationConnectorGroup": "Applications", + "Set-EntraBetaNamedLocationPolicy": "SignIns", + "Get-EntraBetaGroupPermissionGrant": "Groups", + "Update-EntraBetaUserAuthenticationRequirement": "SignIns", + "Get-EntraBetaCustomSecurityAttributeDefinitionAllowedValue": "DirectoryManagement", + "New-EntraBetaDevice": "DirectoryManagement", + "Get-EntraBetaDeviceRegisteredUser": "DirectoryManagement", + "Remove-EntraBetaUserAppRoleAssignment": "Users", + "Get-EntraBetaGroupLifecyclePolicy": "Groups", + "Remove-EntraBetaPasswordSingleSignOnCredential": "Applications", + "Get-EntraBetaApplicationProxyApplicationConnectorGroup": "Applications", + "Set-EntraBetaCustomSecurityAttributeDefinition": "DirectoryManagement", + "Get-EntraBetaUserOAuth2PermissionGrant": "Users", + "Get-EntraBetaContactMembership": "DirectoryManagement", + "Get-EntraContext": "Authentication", + "Set-EntraBetaConditionalAccessPolicy": "SignIns", + "New-EntraBetaApplicationProxyApplication": "Applications", + "Get-EntraBetaGroupMember": "Groups", + "Set-EntraBetaPrivilegedRoleSetting": "Governance", + "Get-EntraBetaDirectorySettingTemplate": "DirectoryManagement", + "Get-EntraBetaApplicationOwner": "Applications", + "Get-EntraBetaServicePrincipalPasswordCredential": "Applications", + "Resolve-EntraBetaTenant": "DirectoryManagement", + "Get-EntraBetaUserOwnedDevice": "Users", + "New-EntraBetaServicePrincipalAppRoleAssignment": "Applications", + "Get-EntraBetaDeletedAdministrativeUnit": "DirectoryManagement", + "Restore-EntraBetaDeletedApplication": "Applications", + "Remove-EntraBetaGroupOwner": "Groups", + "Get-EntraBetaPasswordPolicy": "DirectoryManagement", + "Remove-EntraBetaServicePrincipalPasswordCredential": "Applications", + "New-EntraBetaApplicationPassword": "Applications", + "Set-EntraBetaCustomSecurityAttributeDefinitionAllowedValue": "DirectoryManagement", + "Update-EntraBetaUserFromFederated": "Users", + "New-EntraBetaFeatureRolloutPolicy": "SignIns", + "Add-EntraBetaDeviceRegisteredUser": "DirectoryManagement", + "Get-EntraBetaDevice": "DirectoryManagement", + "New-EntraBetaApplicationPasswordCredential": "Applications", + "Remove-EntraBetaApplicationExtensionProperty": "Applications", + "Get-EntraBetaDirectoryObjectOnPremisesProvisioningError": "DirectoryManagement", + "New-EntraBetaGroupAppRoleAssignment": "Groups", + "Set-EntraBetaDomain": "DirectoryManagement", + "Remove-EntraBetaDeletedApplication": "Applications", + "Get-EntraBetaDeletedDevice": "DirectoryManagement", + "Get-EntraBetaPartnerInformation": "DirectoryManagement", + "New-EntraBetaUserAppRoleAssignment": "Users", + "Remove-EntraBetaServicePrincipalDelegatedPermissionClassification": "Applications", + "Get-EntraBetaDeletedServicePrincipal": "Applications", + "Reset-EntraBetaLifeCycleGroup": "Groups", + "Get-EntraBetaGroupOwner": "Groups", + "Get-EntraBetaDeletedGroup": "Groups", + "Remove-EntraBetaLifecyclePolicyGroup": "Groups", + "Get-EntraBetaUserAuthenticationRequirement": "SignIns", + "Get-EntraBetaDomain": "DirectoryManagement", + "Set-EntraBetaDirSyncConfiguration": "DirectoryManagement", + "Get-EntraBetaUserAuthenticationMethod": "SignIns", + "Add-EntraBetaServicePrincipalOwner": "Applications", + "Get-EntraBetaContactManager": "DirectoryManagement", + "Get-EntraBetaApplicationProxyConnector": "Applications", + "Get-EntraBetaServicePrincipalPolicy": "SignIns", + "Set-EntraBetaDirSyncEnabled": "DirectoryManagement", + "New-EntraBetaGroup": "Groups", + "Remove-EntraBetaDeviceRegisteredOwner": "DirectoryManagement", + "New-EntraBetaOauth2PermissionGrant": "SignIns", + "Get-EntraBetaContact": "DirectoryManagement", + "Remove-EntraBetaUserExtension": "Users", + "Set-EntraBetaApplicationProxyApplicationConnectorGroup": "Applications", + "Remove-EntraBetaPermissionGrantConditionSet": "SignIns", + "Remove-EntraBetaNamedLocationPolicy": "SignIns", + "Get-EntraBetaInactiveSignInUser": "Users", + "Get-EntraBetaTrustedCertificateAuthority": "SignIns", + "Get-EntraBetaDeletedDirectoryObject": "DirectoryManagement", + "Get-EntraBetaApplicationSignInSummary": "Reports", + "New-EntraBetaDirectoryRoleAssignment": "Governance", + "Set-EntraBetaDomainFederationSettings": "DirectoryManagement", + "New-EntraBetaAttributeSet": "DirectoryManagement", + "Get-EntraBetaPrivilegedRoleAssignmentRequest": "Governance", + "Set-EntraBetaUserLicense": "Users", + "Set-EntraBetaApplicationProxyApplication": "Applications", + "Set-EntraBetaPermissionGrantPolicy": "SignIns", + "Get-EntraBetaCrossTenantAccessActivity": "Reports", + "Get-EntraBetaAccountSku": "DirectoryManagement", + "Get-EntraBetaUserDirectReport": "Users", + "Remove-EntraBetaGroupLifecyclePolicy": "Groups", + "Get-EntraBetaServicePrincipalAppRoleAssignment": "Applications", + "Set-EntraBetaPolicy": "SignIns", + "Get-EntraBetaIdentityProvider": "SignIns", + "New-EntraBetaPermissionGrantPolicy": "SignIns", + "Get-EntraBetaFeatureRolloutPolicy": "SignIns", + "Get-EntraBetaDirectoryRoleMember": "DirectoryManagement", + "Get-EntraBetaConditionalAccessPolicy": "SignIns", + "Get-EntraBetaPrivateAccessApplicationSegment": "NetworkAccess", + "Get-EntraBetaUserThumbnailPhoto": "Users", + "Set-EntraBetaGroup": "Groups", + "Remove-EntraBetaDirectoryRoleAssignment": "Governance", + "Disconnect-Entra": "Authentication", + "Remove-EntraBetaObjectSetting": "Groups", + "New-EntraBetaConditionalAccessPolicy": "SignIns", + "Revoke-EntraBetaSignedInUserAllRefreshToken": "Authentication", + "Add-EntraBetaApplicationOwner": "Applications", + "Get-EntraBetaScopedRoleMembership": "DirectoryManagement", + "Get-EntraBetaDirectoryRole": "DirectoryManagement", + "Get-EntraBetaUserMembership": "Users", + "Get-EntraBetaPermissionGrantConditionSet": "SignIns", + "Set-EntraBetaAppRoleToApplicationUser": "Governance", + "Get-EntraBetaUserAdministrativeUnit": "Users", + "Set-EntraBetaApplicationLogo": "Applications", + "Set-EntraBetaTrustedCertificateAuthority": "SignIns", + "Remove-EntraBetaPolicy": "SignIns", + "Get-EntraBetaServicePrincipalKeyCredential": "Applications", + "Remove-EntraBetaDevice": "DirectoryManagement", + "New-EntraBetaApplicationExtensionProperty": "Applications", + "Remove-EntraBetaApplicationOwner": "Applications" +} diff --git a/validations/Validate-EntraModule.ps1 b/validations/Validate-EntraModule.ps1 new file mode 100644 index 0000000000..f546f099e8 --- /dev/null +++ b/validations/Validate-EntraModule.ps1 @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +# ------------------------------------------------------------------------------ +[cmdletbinding()] +param( + + [ValidateSet("Entra", "EntraBeta")] + [string] + $Module = "Entra" +) +. (Join-Path $psscriptroot "./Validator.ps1") + +$validator = [Validator]::new($Module) + +$validator.ValidateScriptSubFoldersMatchDocsSubFolders() +$validator.ValidateScriptSubFolderFilesMatchDocsSubFolderFiles() \ No newline at end of file diff --git a/validations/Validator.ps1 b/validations/Validator.ps1 new file mode 100644 index 0000000000..4b042c4d14 --- /dev/null +++ b/validations/Validator.ps1 @@ -0,0 +1,75 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +# ------------------------------------------------------------------------------ +Set-StrictMode -Version 5 + +class Validator { + [string] $RootModuleName + [string] $DocFolderName + [string] $ScriptsFolderPath + [string] $DocsFolderPath + [string[]] $SubModules + + # Constructor to initialize the validation paths based on the module name + Validator([string] $Module) { + + if($Module -eq 'Entra'){ + $this.RootModuleName = 'Microsoft.Entra' + $this.DocFolderName = 'entra-powershell-v1.0' + $this.SubModules = @('Authentication', 'Applications', 'DirectoryManagement', 'Governance', 'Groups', 'Users', 'Reports', 'SignIns', 'CertificateBasedAuthentication') + } + elseif($Module -eq 'EntraBeta'){ + $this.RootModuleName = 'Microsoft.Entra.Beta' + $this.DocFolderName = 'entra-powershell-beta' + $this.SubModules = @('Authentication', 'Applications', 'DirectoryManagement', 'Governance', 'Groups', 'Users', 'Reports', 'SignIns', 'NetworkAccess') + } + + $this.ScriptsFolderPath = (Join-Path $PSScriptRoot "../module/$Module/$($this.RootModuleName)") + $this.DocsFolderPath = (Join-Path $PSScriptRoot "../module/docs/$($this.DocFolderName)") + } + + # Method to validate that script subfolders match docs subfolders + ValidateScriptSubFoldersMatchDocsSubFolders() { + $scriptSubModules = @(Get-ChildItem -Path $this.ScriptsFolderPath -Directory) + $docSubModules = @(Get-ChildItem -Path $this.DocsFolderPath -Directory) + if($scriptSubModules.Count -ne $docSubModules.Count){ + Write-Host "Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count))." -ForegroundColor 'Red' + } + + $missingScriptFolders = @() + $missingDocFolders = @() + foreach($scriptSubModule in $scriptSubModules){ + if($docSubModules.Name -notcontains $scriptSubModule.Name){ + Write-Host "Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder." -ForegroundColor 'Red' + } + } + foreach($docSubModule in $docSubModules){ + if($scriptSubModules.Name -notcontains $docSubModule.Name){ + Write-Host "Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder." -ForegroundColor 'Red' + } + } + } + + # Method to validate that script subfolder files match docs subfolder files + ValidateScriptSubFolderFilesMatchDocsSubFolderFiles() { + foreach($subModule in $this.SubModules){ + $scriptFiles = @(Get-ChildItem -Path (Join-Path $this.ScriptsFolderPath $subModule) -Filter *.ps1 | Where-Object { $_.Name -ne "New-EntraCustomHeaders.ps1" -and $_.Name -ne "New-EntraBetaCustomHeaders.ps1" }) + $docFiles = @(Get-ChildItem -Path (Join-Path $this.DocsFolderPath $subModule) -File) + if($scriptFiles.Count -ne $docFiles.Count){ + Write-Host "Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count))." -ForegroundColor 'Red' + } + + foreach($scriptFile in $scriptFiles){ + if($docFiles.BaseName -notcontains $scriptFile.BaseName){ + Write-Host "Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file." -ForegroundColor 'Red' + } + } + + foreach($docFile in $docFiles){ + if($scriptFiles.BaseName -notcontains $docFile.BaseName){ + Write-Host "Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file." -ForegroundColor 'Red' + } + } + } + } +} \ No newline at end of file From 2f63b3c2c83ef7b78568af7907ed7a15bdc997e8 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Thu, 17 Jul 2025 12:50:09 +0300 Subject: [PATCH 03/10] Run validations on pipeline --- .../generation-templates/generate_adapter-1es.yml | 8 ++++++++ validations/Validate-EntraModule.ps1 | 4 ++-- validations/Validate.ps1 | 0 3 files changed, 10 insertions(+), 2 deletions(-) delete mode 100644 validations/Validate.ps1 diff --git a/.azure-pipelines/generation-templates/generate_adapter-1es.yml b/.azure-pipelines/generation-templates/generate_adapter-1es.yml index e146f9ab11..5c1a31a653 100644 --- a/.azure-pipelines/generation-templates/generate_adapter-1es.yml +++ b/.azure-pipelines/generation-templates/generate_adapter-1es.yml @@ -23,6 +23,14 @@ steps: targetType: inline script: '$MaximumFunctionCount=32768' pwsh: true +- task: powershell@2 + displayName: 'Run Validations' + inputs: + targetType: inline + script: | + . ./validations/Validate-EntraModule.ps1 -ModuleName Entra -Verbose + . ./validations/Validate-EntraModule.ps1 -ModuleName EntraBeta -Verbose + pwsh: true - task: powershell@2 displayName: 'Install Dependencies Entra' inputs: diff --git a/validations/Validate-EntraModule.ps1 b/validations/Validate-EntraModule.ps1 index f546f099e8..b657ca274a 100644 --- a/validations/Validate-EntraModule.ps1 +++ b/validations/Validate-EntraModule.ps1 @@ -6,11 +6,11 @@ param( [ValidateSet("Entra", "EntraBeta")] [string] - $Module = "Entra" + $ModuleName = "Entra" ) . (Join-Path $psscriptroot "./Validator.ps1") -$validator = [Validator]::new($Module) +$validator = [Validator]::new($ModuleName) $validator.ValidateScriptSubFoldersMatchDocsSubFolders() $validator.ValidateScriptSubFolderFilesMatchDocsSubFolderFiles() \ No newline at end of file diff --git a/validations/Validate.ps1 b/validations/Validate.ps1 deleted file mode 100644 index e69de29bb2..0000000000 From 14e19e40dbffe3aaca04350b8f6f5da44bb46bf6 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Thu, 17 Jul 2025 14:12:38 +0300 Subject: [PATCH 04/10] Write-Error --- validations/Validator.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/validations/Validator.ps1 b/validations/Validator.ps1 index 4b042c4d14..82ce8c07de 100644 --- a/validations/Validator.ps1 +++ b/validations/Validator.ps1 @@ -33,41 +33,41 @@ class Validator { $scriptSubModules = @(Get-ChildItem -Path $this.ScriptsFolderPath -Directory) $docSubModules = @(Get-ChildItem -Path $this.DocsFolderPath -Directory) if($scriptSubModules.Count -ne $docSubModules.Count){ - Write-Host "Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count))." -ForegroundColor 'Red' + Write-Error "Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count))." } $missingScriptFolders = @() $missingDocFolders = @() foreach($scriptSubModule in $scriptSubModules){ if($docSubModules.Name -notcontains $scriptSubModule.Name){ - Write-Host "Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder." -ForegroundColor 'Red' + Write-Error "Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder." } } foreach($docSubModule in $docSubModules){ if($scriptSubModules.Name -notcontains $docSubModule.Name){ - Write-Host "Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder." -ForegroundColor 'Red' + Write-Error "Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder." } } } - + # Method to validate that script subfolder files match docs subfolder files ValidateScriptSubFolderFilesMatchDocsSubFolderFiles() { foreach($subModule in $this.SubModules){ $scriptFiles = @(Get-ChildItem -Path (Join-Path $this.ScriptsFolderPath $subModule) -Filter *.ps1 | Where-Object { $_.Name -ne "New-EntraCustomHeaders.ps1" -and $_.Name -ne "New-EntraBetaCustomHeaders.ps1" }) $docFiles = @(Get-ChildItem -Path (Join-Path $this.DocsFolderPath $subModule) -File) if($scriptFiles.Count -ne $docFiles.Count){ - Write-Host "Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count))." -ForegroundColor 'Red' + Write-Error "Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count))." } foreach($scriptFile in $scriptFiles){ if($docFiles.BaseName -notcontains $scriptFile.BaseName){ - Write-Host "Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file." -ForegroundColor 'Red' + Write-Error "Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file." } } foreach($docFile in $docFiles){ if($scriptFiles.BaseName -notcontains $docFile.BaseName){ - Write-Host "Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file." -ForegroundColor 'Red' + Write-Error "Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file." } } } From 8829caaaf9ef68a5fc5e6d12b7040328676a3096 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Thu, 17 Jul 2025 14:22:15 +0300 Subject: [PATCH 05/10] failOnStderr false --- .azure-pipelines/generation-templates/generate_adapter-1es.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure-pipelines/generation-templates/generate_adapter-1es.yml b/.azure-pipelines/generation-templates/generate_adapter-1es.yml index 5c1a31a653..20a2b488e6 100644 --- a/.azure-pipelines/generation-templates/generate_adapter-1es.yml +++ b/.azure-pipelines/generation-templates/generate_adapter-1es.yml @@ -31,6 +31,7 @@ steps: . ./validations/Validate-EntraModule.ps1 -ModuleName Entra -Verbose . ./validations/Validate-EntraModule.ps1 -ModuleName EntraBeta -Verbose pwsh: true + failOnStderr: false - task: powershell@2 displayName: 'Install Dependencies Entra' inputs: From 1d81513022c4778ea3ff997ae1d06386c3239f6b Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Fri, 18 Jul 2025 10:17:19 +0300 Subject: [PATCH 06/10] Refactor output --- validations/Validator.ps1 | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/validations/Validator.ps1 b/validations/Validator.ps1 index 82ce8c07de..d28c0eeb15 100644 --- a/validations/Validator.ps1 +++ b/validations/Validator.ps1 @@ -33,19 +33,19 @@ class Validator { $scriptSubModules = @(Get-ChildItem -Path $this.ScriptsFolderPath -Directory) $docSubModules = @(Get-ChildItem -Path $this.DocsFolderPath -Directory) if($scriptSubModules.Count -ne $docSubModules.Count){ - Write-Error "Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count))." + $this.WriteWarning("Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count)).") } $missingScriptFolders = @() $missingDocFolders = @() foreach($scriptSubModule in $scriptSubModules){ if($docSubModules.Name -notcontains $scriptSubModule.Name){ - Write-Error "Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder." + $this.WriteWarning("Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder.") } } foreach($docSubModule in $docSubModules){ if($scriptSubModules.Name -notcontains $docSubModule.Name){ - Write-Error "Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder." + $this.WriteWarning("Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder.") } } } @@ -56,20 +56,30 @@ class Validator { $scriptFiles = @(Get-ChildItem -Path (Join-Path $this.ScriptsFolderPath $subModule) -Filter *.ps1 | Where-Object { $_.Name -ne "New-EntraCustomHeaders.ps1" -and $_.Name -ne "New-EntraBetaCustomHeaders.ps1" }) $docFiles = @(Get-ChildItem -Path (Join-Path $this.DocsFolderPath $subModule) -File) if($scriptFiles.Count -ne $docFiles.Count){ - Write-Error "Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count))." + $this.WriteWarning("Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count)).") } foreach($scriptFile in $scriptFiles){ if($docFiles.BaseName -notcontains $scriptFile.BaseName){ - Write-Error "Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file." + $this.WriteWarning("Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file.") } } foreach($docFile in $docFiles){ if($scriptFiles.BaseName -notcontains $docFile.BaseName){ - Write-Error "Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file." + $this.WriteWarning("Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file.") } } } } + + hidden WriteWarning([string] $message) { + #Write-Host "WARNING: $message" -ForegroundColor Yellow + Write-Warning "$message" + } + + hidden WriteError([string] $message) { + Write-Host "ERROR: $message" -ForegroundColor Red + throw $message + } } \ No newline at end of file From 0c1b3f2decd09418bc17a4b680fad4a92561a919 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Fri, 18 Jul 2025 10:32:18 +0300 Subject: [PATCH 07/10] Test output --- validations/Validator.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/validations/Validator.ps1 b/validations/Validator.ps1 index d28c0eeb15..59a24e9d03 100644 --- a/validations/Validator.ps1 +++ b/validations/Validator.ps1 @@ -75,7 +75,8 @@ class Validator { hidden WriteWarning([string] $message) { #Write-Host "WARNING: $message" -ForegroundColor Yellow - Write-Warning "$message" + #Write-Warning "$message" + Write-Host "##vso[task.logissue type=error] $message" } hidden WriteError([string] $message) { From 20ab41a86686fce7dd5912d4968ab7db42c0b8df Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Fri, 18 Jul 2025 10:47:48 +0300 Subject: [PATCH 08/10] Fail pipeline --- validations/Validate-EntraModule.ps1 | 5 ++++- validations/Validator.ps1 | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/validations/Validate-EntraModule.ps1 b/validations/Validate-EntraModule.ps1 index b657ca274a..e9e1e49c2d 100644 --- a/validations/Validate-EntraModule.ps1 +++ b/validations/Validate-EntraModule.ps1 @@ -13,4 +13,7 @@ param( $validator = [Validator]::new($ModuleName) $validator.ValidateScriptSubFoldersMatchDocsSubFolders() -$validator.ValidateScriptSubFolderFilesMatchDocsSubFolderFiles() \ No newline at end of file +$validator.ValidateScriptSubFolderFilesMatchDocsSubFolderFiles() + +# Exit the pipeline with an error if any validation failed +$validator.ExitPipeline() \ No newline at end of file diff --git a/validations/Validator.ps1 b/validations/Validator.ps1 index 59a24e9d03..cff0618a20 100644 --- a/validations/Validator.ps1 +++ b/validations/Validator.ps1 @@ -9,6 +9,7 @@ class Validator { [string] $ScriptsFolderPath [string] $DocsFolderPath [string[]] $SubModules + hidden [int] $ErrorCount # Constructor to initialize the validation paths based on the module name Validator([string] $Module) { @@ -26,6 +27,7 @@ class Validator { $this.ScriptsFolderPath = (Join-Path $PSScriptRoot "../module/$Module/$($this.RootModuleName)") $this.DocsFolderPath = (Join-Path $PSScriptRoot "../module/docs/$($this.DocFolderName)") + $this.ErrorCount = 0 } # Method to validate that script subfolders match docs subfolders @@ -33,6 +35,7 @@ class Validator { $scriptSubModules = @(Get-ChildItem -Path $this.ScriptsFolderPath -Directory) $docSubModules = @(Get-ChildItem -Path $this.DocsFolderPath -Directory) if($scriptSubModules.Count -ne $docSubModules.Count){ + $this.ErrorCount++ $this.WriteWarning("Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count)).") } @@ -40,11 +43,13 @@ class Validator { $missingDocFolders = @() foreach($scriptSubModule in $scriptSubModules){ if($docSubModules.Name -notcontains $scriptSubModule.Name){ + $this.ErrorCount++ $this.WriteWarning("Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder.") } } foreach($docSubModule in $docSubModules){ if($scriptSubModules.Name -notcontains $docSubModule.Name){ + $this.ErrorCount++ $this.WriteWarning("Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder.") } } @@ -56,17 +61,20 @@ class Validator { $scriptFiles = @(Get-ChildItem -Path (Join-Path $this.ScriptsFolderPath $subModule) -Filter *.ps1 | Where-Object { $_.Name -ne "New-EntraCustomHeaders.ps1" -and $_.Name -ne "New-EntraBetaCustomHeaders.ps1" }) $docFiles = @(Get-ChildItem -Path (Join-Path $this.DocsFolderPath $subModule) -File) if($scriptFiles.Count -ne $docFiles.Count){ + $this.ErrorCount++ $this.WriteWarning("Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count)).") } foreach($scriptFile in $scriptFiles){ if($docFiles.BaseName -notcontains $scriptFile.BaseName){ + $this.ErrorCount++ $this.WriteWarning("Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file.") } } foreach($docFile in $docFiles){ if($scriptFiles.BaseName -notcontains $docFile.BaseName){ + $this.ErrorCount++ $this.WriteWarning("Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file.") } } @@ -83,4 +91,13 @@ class Validator { Write-Host "ERROR: $message" -ForegroundColor Red throw $message } + + ExitPipeline() { + if($this.ErrorCount -gt 0){ + $this.WriteError("Validation failed with $($this.ErrorCount) errors.") + } + else { + Write-Host "Validation completed successfully." + } + } } \ No newline at end of file From 0b058f5074189802f888f271a2c0bcfc3151f973 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Fri, 18 Jul 2025 11:17:31 +0300 Subject: [PATCH 09/10] Refactor error messages --- validations/Validate-EntraModule.ps1 | 5 ++++- validations/Validator.ps1 | 25 ++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/validations/Validate-EntraModule.ps1 b/validations/Validate-EntraModule.ps1 index e9e1e49c2d..890b92697f 100644 --- a/validations/Validate-EntraModule.ps1 +++ b/validations/Validate-EntraModule.ps1 @@ -12,8 +12,11 @@ param( $validator = [Validator]::new($ModuleName) +Write-Host "[Invocation] ScriptName $($PSCmdlet.MyInvocation.ScriptName)." +Write-Host "[Invocation] CommandOrigin $($PSCmdlet.MyInvocation.CommandOrigin)." + $validator.ValidateScriptSubFoldersMatchDocsSubFolders() $validator.ValidateScriptSubFolderFilesMatchDocsSubFolderFiles() # Exit the pipeline with an error if any validation failed -$validator.ExitPipeline() \ No newline at end of file +$validator.ExitPipeline() diff --git a/validations/Validator.ps1 b/validations/Validator.ps1 index cff0618a20..0d2ac18f17 100644 --- a/validations/Validator.ps1 +++ b/validations/Validator.ps1 @@ -36,7 +36,7 @@ class Validator { $docSubModules = @(Get-ChildItem -Path $this.DocsFolderPath -Directory) if($scriptSubModules.Count -ne $docSubModules.Count){ $this.ErrorCount++ - $this.WriteWarning("Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count)).") + $this.LogError("Script submodules folders count ($($scriptSubModules.Count)) does not match docs submodules folders count ($($docSubModules.Count)).") } $missingScriptFolders = @() @@ -44,13 +44,13 @@ class Validator { foreach($scriptSubModule in $scriptSubModules){ if($docSubModules.Name -notcontains $scriptSubModule.Name){ $this.ErrorCount++ - $this.WriteWarning("Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder.") + $this.LogError("Script submodule folder '$($scriptSubModule.Name)' does not have a corresponding docs submodule folder.") } } foreach($docSubModule in $docSubModules){ if($scriptSubModules.Name -notcontains $docSubModule.Name){ $this.ErrorCount++ - $this.WriteWarning("Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder.") + $this.LogError("Doc submodule folder '$($docSubModule.Name)' does not have a corresponding script submodule folder.") } } } @@ -62,39 +62,38 @@ class Validator { $docFiles = @(Get-ChildItem -Path (Join-Path $this.DocsFolderPath $subModule) -File) if($scriptFiles.Count -ne $docFiles.Count){ $this.ErrorCount++ - $this.WriteWarning("Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count)).") + $this.LogError("Script submodule folder '$subModule' files count ($($scriptFiles.Count)) does not match docs submodule folder '$subModule' files count ($($docFiles.Count)).") } foreach($scriptFile in $scriptFiles){ if($docFiles.BaseName -notcontains $scriptFile.BaseName){ $this.ErrorCount++ - $this.WriteWarning("Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file.") + $this.LogError("Script file '$($scriptFile.BaseName)' in subfolder '$subModule' does not have a corresponding doc file.") } } foreach($docFile in $docFiles){ if($scriptFiles.BaseName -notcontains $docFile.BaseName){ $this.ErrorCount++ - $this.WriteWarning("Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file.") + $this.LogError("Doc file '$($docFile.BaseName)' in subfolder '$subModule' does not have a corresponding script file.") } } } } - hidden WriteWarning([string] $message) { - #Write-Host "WARNING: $message" -ForegroundColor Yellow - #Write-Warning "$message" - Write-Host "##vso[task.logissue type=error] $message" + hidden LogError([string] $message) { + Write-Host "##vso[task.logissue type=error] $message" -ForegroundColor Red } hidden WriteError([string] $message) { - Write-Host "ERROR: $message" -ForegroundColor Red - throw $message + Write-Host "$message" -ForegroundColor Red } ExitPipeline() { if($this.ErrorCount -gt 0){ - $this.WriteError("Validation failed with $($this.ErrorCount) errors.") + $message = "Validation failed with $($this.ErrorCount) errors." + $this.WriteError($message) + exit 1 } else { Write-Host "Validation completed successfully." From 815b6b780a235c8baa2ddc7d0ab9535e9c545a30 Mon Sep 17 00:00:00 2001 From: Kennedy Kangethe Munga Date: Fri, 18 Jul 2025 15:04:49 +0300 Subject: [PATCH 10/10] Code cleanup --- validations/Validate-EntraModule.ps1 | 3 --- 1 file changed, 3 deletions(-) diff --git a/validations/Validate-EntraModule.ps1 b/validations/Validate-EntraModule.ps1 index 890b92697f..804bc7b120 100644 --- a/validations/Validate-EntraModule.ps1 +++ b/validations/Validate-EntraModule.ps1 @@ -12,9 +12,6 @@ param( $validator = [Validator]::new($ModuleName) -Write-Host "[Invocation] ScriptName $($PSCmdlet.MyInvocation.ScriptName)." -Write-Host "[Invocation] CommandOrigin $($PSCmdlet.MyInvocation.CommandOrigin)." - $validator.ValidateScriptSubFoldersMatchDocsSubFolders() $validator.ValidateScriptSubFolderFilesMatchDocsSubFolderFiles()