diff --git a/Cache_SAMSetup/SAMManifestNoPartner.json b/Cache_SAMSetup/SAMManifestNoPartner.json deleted file mode 100644 index 37f6c62fc909..000000000000 --- a/Cache_SAMSetup/SAMManifestNoPartner.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "isFallbackPublicClient": true, - "signInAudience": "AzureADMyOrg", - "displayName": "CIPP-SAM", - "web": { - "redirectUris": [ - "https://login.microsoftonline.com/common/oauth2/nativeclient", - "https://localhost", - "http://localhost", - "http://localhost:8400" - ] - }, - "requiredResourceAccess": [ - { - "resourceAppId": "00000003-0000-0000-c000-000000000000", - "resourceAccess": [ - { "id": "0f4595f7-64b1-4e13-81bc-11a249df07a9", "type": "Scope" }, - { "id": "73e75199-7c3e-41bb-9357-167164dbb415", "type": "Scope" }, - { "id": "7ab1d787-bae7-4d5d-8db6-37ea32df9186", "type": "Scope" }, - { "id": "d01b97e9-cbc0-49fe-810a-750afd5527a3", "type": "Scope" }, - { "id": "46ca0847-7e6b-426e-9775-ea810a948356", "type": "Scope" }, - { "id": "dc38509c-b87d-4da0-bd92-6bec988bac4a", "type": "Scope" }, - { "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182", "type": "Scope" }, - { "id": "ad902697-1014-4ef5-81ef-2b4301988e8c", "type": "Scope" }, - { "id": "572fea84-0151-49b2-9301-11cb16974376", "type": "Scope" }, - { "id": "e4c9e354-4dc5-45b8-9e7c-e1393b0b1a20", "type": "Scope" }, - { "id": "0883f392-0a7a-443d-8c76-16a6d39c7b63", "type": "Scope" }, - { "id": "7b3f05d5-f68c-4b8d-8c59-a2ecd12f24af", "type": "Scope" }, - { "id": "0c5e8a55-87a6-4556-93ab-adc52c4d862d", "type": "Scope" }, - { "id": "44642bfe-8385-4adc-8fc6-fe3cb2c375c3", "type": "Scope" }, - { "id": "662ed50a-ac44-4eef-ad86-62eed9be2a29", "type": "Scope" }, - { "id": "8696daa5-bce5-4b2e-83f9-51b6defc4e1e", "type": "Scope" }, - { "id": "6aedf524-7e1c-45a7-bd76-ded8cab8d0fc", "type": "Scope" }, - { "id": "bac3b9c2-b516-4ef4-bd3b-c2ef73d8d804", "type": "Scope" }, - { "id": "11d4cd79-5ba5-460f-803f-e22c8ab85ccd", "type": "Scope" }, - { "id": "02e97553-ed7b-43d0-ab3c-f8bace0d040c", "type": "Scope" }, - { "id": "89fe6a52-be36-487e-b7d8-d061c450a026", "type": "Scope" }, - { "id": "a367ab51-6b49-43bf-a716-a1fb06d2a174", "type": "Scope" }, - { "id": "204e0828-b5ca-4ad8-b9f3-f32a958e7cc4", "type": "Scope" }, - { "id": "4e46008b-f24c-477d-8fff-7bb4ec7aafe0", "type": "Scope" }, - { "id": "0e263e50-5827-48a4-b97c-d940288653c7", "type": "Scope" }, - { "id": "e383f46e-2787-4529-855e-0e479a3ffac0", "type": "Scope" }, - { "id": "37f7f235-527c-4136-accd-4a02d197296e", "type": "Scope" }, - { "id": "14dad69e-099b-42c9-810b-d002981feec1", "type": "Scope" }, - { "id": "f6a3db3e-f7e8-4ed2-a414-557c8c9830be", "type": "Scope" }, - { "id": "0e755559-83fb-4b44-91d0-4cc721b9323e", "type": "Scope" }, - { "id": "a84a9652-ffd3-496e-a991-22ba5529156a", "type": "Scope" }, - { "id": "1d89d70c-dcac-4248-b214-903c457af83a", "type": "Scope" }, - { "id": "32ea53ac-4a89-4cde-bac4-727c6fb9ac29", "type": "Scope" }, - { "id": "2b61aa8a-6d36-4b2f-ac7b-f29867937c53", "type": "Scope" }, - { "id": "ebf0f66e-9fb1-49e4-a278-222f76911cf4", "type": "Scope" }, - { "id": "daef10fc-047a-48b0-b1a5-da4b5e72fabc", "type": "Scope" }, - { "id": "2a5addc2-4d9e-4d7d-8527-5215aec410f3", "type": "Scope" }, - { "id": "c79f8feb-a9db-4090-85f9-90d820caa0eb", "type": "Scope" }, - { "id": "bdfbf15f-ee85-4955-8675-146e8e5296b5", "type": "Scope" }, - { "id": "f81125ac-d3b7-4573-a3b2-7099cc39df9e", "type": "Scope" }, - { "id": "cac97e40-6730-457d-ad8d-4852fddab7ad", "type": "Scope" }, - { "id": "b7887744-6746-4312-813d-72daeaee7e2d", "type": "Scope" }, - { "id": "48971fc1-70d7-4245-af77-0beb29b53ee2", "type": "Scope" }, - { "id": "aec28ec7-4d02-4e8c-b864-50163aea77eb", "type": "Scope" }, - { "id": "d3f0af02-b22d-4778-a433-14f7e3f2e1e2", "type": "Scope" }, - { "id": "9127ba42-f79f-43b1-be80-f23ecd42377e", "type": "Scope" }, - { "id": "a9ff19c2-f369-4a95-9a25-ba9d460efc8e", "type": "Scope" }, - { "id": "59dacb05-e88d-4c13-a684-59f1afc8cc98", "type": "Scope" }, - { "id": "b98bfd41-87c6-45cc-b104-e2de4f0dafb9", "type": "Scope" }, - { "id": "2f9ee017-59c1-4f1d-9472-bd5529a7b311", "type": "Scope" }, - { "id": "951183d1-1a61-466f-a6d1-1fde911bfd95", "type": "Scope" }, - { "id": "637d7bec-b31e-4deb-acc9-24275642a2c9", "type": "Scope" }, - { "id": "101147cf-4178-4455-9d58-02b5c164e759", "type": "Scope" }, - { "id": "cc83893a-e232-4723-b5af-bd0b01bcfe65", "type": "Scope" }, - { "id": "233e0cf1-dd62-48bc-b65b-b38fe87fcf8e", "type": "Scope" }, - { "id": "d649fb7c-72b4-4eec-b2b4-b15acf79e378", "type": "Scope" }, - { "id": "485be79e-c497-4b35-9400-0e3fa7f2a5d4", "type": "Scope" }, - { "id": "9d8982ae-4365-4f57-95e9-d6032a4c0b87", "type": "Scope" }, - { "id": "48638b3c-ad68-4383-8ac4-e6880ee6ca57", "type": "Scope" }, - { "id": "39d65650-9d3e-4223-80db-a335590d027e", "type": "Scope" }, - { "id": "4a06efd2-f825-4e34-813e-82a57b03d1ee", "type": "Scope" }, - { "id": "f3bfad56-966e-4590-a536-82ecf548ac1e", "type": "Scope" }, - { "id": "4d135e65-66b8-41a8-9f8b-081452c91774", "type": "Scope" }, - { "id": "2eadaff8-0bce-4198-a6b9-2cfc35a30075", "type": "Scope" }, - { "id": "0c3e411a-ce45-4cd1-8f30-f99a3efa7b11", "type": "Scope" }, - { "id": "edb72de9-4252-4d03-a925-451deef99db7", "type": "Scope" }, - { "id": "767156cb-16ae-4d10-8f8b-41b657c8c8c8", "type": "Scope" }, - { "id": "7e823077-d88e-468f-a337-e18f1f0e6c7c", "type": "Scope" }, - { "id": "edd3c878-b384-41fd-95ad-e7407dd775be", "type": "Scope" }, - { "id": "40b534c3-9552-4550-901b-23879c90bcf9", "type": "Scope" }, - { "id": "bf3fbf03-f35f-4e93-963e-47e4d874c37a", "type": "Scope" }, - { "id": "5248dcb1-f83b-4ec3-9f4d-a4428a961a72", "type": "Scope" }, - { "id": "c395395c-ff9a-4dba-bc1f-8372ba9dca84", "type": "Scope" }, - { "id": "2e25a044-2580-450d-8859-42eeb6e996c0", "type": "Scope" }, - { "id": "0ce33576-30e8-43b7-99e5-62f8569a4002", "type": "Scope" }, - { "id": "207e0cb1-3ce7-4922-b991-5a760c346ebc", "type": "Scope" }, - { "id": "093f8818-d05f-49b8-95bc-9d2a73e9a43c", "type": "Scope" }, - { "id": "7825d5d6-6049-4ce7-bdf6-3b8d53f4bcd0", "type": "Scope" }, - { "id": "2104a4db-3a2f-4ea0-9dba-143d457dc666", "type": "Scope" }, - { "id": "eda39fa6-f8cf-4c3c-a909-432c683e4c9b", "type": "Scope" }, - { "id": "55896846-df78-47a7-aa94-8d3d4442ca7f", "type": "Scope" }, - { "id": "aa85bf13-d771-4d5d-a9e6-bca04ce44edf", "type": "Scope" }, - { "id": "ee928332-e9c2-4747-b4a0-f8c164b68de6", "type": "Scope" }, - { "id": "c975dd04-a06e-4fbb-9704-62daad77bb49", "type": "Scope" }, - { "id": "c37c9b61-7762-4bff-a156-afc0005847a0", "type": "Scope" }, - { "id": "999f8c63-0a38-4f1b-91fd-ed1947bdd1a9", "type": "Role" }, - { "id": "292d869f-3427-49a8-9dab-8c70152b74e9", "type": "Role" }, - { "id": "2f51be20-0bb4-4fed-bf7b-db946066c75e", "type": "Role" }, - { "id": "58ca0d9a-1575-47e1-a3cb-007ef2e4583b", "type": "Role" }, - { "id": "06a5fe6d-c49d-46a7-b082-56b1b14103c7", "type": "Role" }, - { "id": "246dd0d5-5bd0-4def-940b-0421030a5b68", "type": "Role" }, - { "id": "bf394140-e372-4bf9-a898-299cfc7564e5", "type": "Role" }, - { "id": "741f803b-c850-494e-b5df-cde7c675a1ca", "type": "Role" }, - { "id": "230c1aed-a721-4c5d-9cb4-a90514e508ef", "type": "Role" }, - { "id": "b633e1c5-b582-4048-a93e-9f11b44c7e96", "type": "Role" }, - { "id": "5b567255-7703-4780-807c-7be8301ae99b", "type": "Role" }, - { "id": "62a82d76-70ea-41e2-9197-370581804d09", "type": "Role" }, - { "id": "7ab1d382-f21e-4acd-a863-ba3e13f7da61", "type": "Role" }, - { "id": "1138cb37-bd11-4084-a2b7-9f71582aeddb", "type": "Role" }, - { "id": "78145de6-330d-4800-a6ce-494ff2d33d07", "type": "Role" }, - { "id": "9241abd9-d0e6-425a-bd4f-47ba86e767a4", "type": "Role" }, - { "id": "5b07b0dd-2377-4e44-a38d-703f09a0dc3c", "type": "Role" }, - { "id": "243333ab-4d21-40cb-a475-36241daa0842", "type": "Role" }, - { "id": "e330c4f0-4170-414e-a55a-2f022ec2b57b", "type": "Role" }, - { "id": "5ac13192-7ace-4fcf-b828-1a26f28068ee", "type": "Role" }, - { "id": "2f6817f8-7b12-4f0f-bc18-eeaf60705a9e", "type": "Role" }, - { "id": "dbaae8cf-10b5-4b86-a4a1-f871c94c6695", "type": "Role" }, - { "id": "bf7b1a76-6e77-406b-b258-bf5c7720e98f", "type": "Role" }, - { "id": "01c0a623-fc9b-48e9-b794-0756f8e8f067", "type": "Role" }, - { "id": "50483e42-d915-4231-9639-7fdb7fd190e5", "type": "Role" }, - { "id": "dbb9058a-0e50-45d7-ae91-66909b5d4664", "type": "Role" }, - { "id": "a82116e5-55eb-4c41-a434-62fe8a61c773", "type": "Role" }, - { "id": "f3a65bd4-b703-46df-8f7e-0174fea562aa", "type": "Role" }, - { "id": "59a6b24b-4225-4393-8165-ebaec5f55d7a", "type": "Role" }, - { "id": "0121dc95-1b9f-4aed-8bac-58c5ac466691", "type": "Role" }, - { "id": "3b55498e-47ec-484f-8136-9013221c06a9", "type": "Role" }, - { "id": "35930dcf-aceb-4bd1-b99a-8ffed403c974", "type": "Role" }, - { "id": "25f85f3c-f66c-4205-8cd5-de92dd7f0cec", "type": "Role" }, - { "id": "29c18626-4985-4dcd-85c0-193eef327366", "type": "Role" }, - { "id": "4437522e-9a86-4a41-a7da-e380edd4a97d", "type": "Role" } - ] - }, - { - "resourceAppId": "00000002-0000-0000-c000-000000000000", - "resourceAccess": [ - { "id": "5778995a-e1bf-45b8-affa-663a9f3f4d04", "type": "Role" }, - { "id": "a42657d6-7f20-40e3-b6f0-cee03008a62a", "type": "Scope" }, - { "id": "311a71cc-e848-46a1-bdf8-97ff7156d8e6", "type": "Scope" } - ] - } - ] -} diff --git a/Config/StandardsTable.BPATemplate.json b/Config/StandardsTable.BPATemplate.json new file mode 100644 index 000000000000..858b1b462fca --- /dev/null +++ b/Config/StandardsTable.BPATemplate.json @@ -0,0 +1,534 @@ +{ + "name": "CIPP Standards v1.0 - Table view", + "style": "Table", + "Fields": [ + { + "name": "ActivityBasedTimeout", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "ActivityBasedTimeout", + "value": "ActivityBasedTimeout" + } + ] + }, + { + "name": "softwareOath", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "softwareOath", + "value": "softwareOath" + } + ] + }, + { + "name": "MSAuthenticator", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "MSAuthenticator", + "value": "MSAuthenticator" + } + ] + }, + { + "name": "AnonReport", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "AnonReport", + "value": "AnonReport" + } + ] + }, + { + "name": "AuditLog", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "AuditLog", + "value": "AuditLog" + } + ] + }, + { + "name": "AutoExpandingArchive", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "AutoExpandingArchive", + "value": "AutoExpandingArchive" + } + ] + }, + { + "name": "DelegateSentItems", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "DelegateSentItems", + "value": "DelegateSentItems" + } + ] + }, + { + "name": "DeletedUserRentention", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DeletedUserRentention", + "value": "DeletedUserRentention" + } + ] + }, + { + "name": "DisableBasicAuthSMTP", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableBasicAuthSMTP", + "value": "DisableBasicAuthSMTP" + } + ] + }, + { + "name": "DisableGuestDirectory", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableGuestDirectory", + "value": "DisableGuestDirectory" + } + ] + }, + { + "name": "DisableGuests", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "DisableGuests", + "value": "DisableGuests" + } + ] + }, + { + "name": "DisableM365GroupUsers", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableM365GroupUsers", + "value": "DisableM365GroupUsers" + } + ] + }, + { + "name": "MacSync", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "MacSync", + "value": "MacSync" + } + ] + }, + { + "name": "DisableReshare", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableReshare", + "value": "DisableReshare" + } + ] + }, + { + "name": "DisableSecurityGroupUsers", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableSecurityGroupUsers", + "value": "DisableSecurityGroupUsers" + } + ] + }, + { + "name": "DisableSharedMailbox", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "DisableSharedMailbox", + "value": "DisableSharedMailbox" + } + ] + }, + { + "name": "DisableTenantCreation", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableTenantCreation", + "value": "DisableTenantCreation" + } + ] + }, + { + "name": "DisableUserSiteCreate", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableUserSiteCreate", + "value": "DisableUserSiteCreate" + } + ] + }, + { + "name": "DisableViva", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "DisableViva", + "value": "DisableViva" + } + ] + }, + { + "name": "EnableAppConsentAdminRequests", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "EnableAppConsentAdminRequests", + "value": "EnableAppConsentAdminRequests" + } + ] + }, + { + "name": "EnableFIDO2", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "EnableFIDO2", + "value": "EnableFIDO2" + } + ] + }, + { + "name": "EnableOnlineArchiving", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "EnableOnlineArchiving", + "value": "EnableOnlineArchiving" + } + ] + }, + { + "name": "ExcludedfileExt", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "ExcludedfileExt", + "value": "ExcludedfileExt" + } + ] + }, + { + "name": "intuneDeviceReg", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "intuneDeviceReg", + "value": "intuneDeviceReg" + } + ] + }, + { + "name": "intuneDeviceRetirementDays", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "intuneDeviceRetirementDays", + "value": "intuneDeviceRetirementDays" + } + ] + }, + { + "name": "intuneRequireMFA", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "intuneRequireMFA", + "value": "intuneRequireMFA" + } + ] + }, + { + "name": "laps", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "laps", + "value": "laps" + } + ] + }, + { + "name": "MailContacts", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "MailContacts", + "value": "MailContacts" + } + ] + }, + { + "name": "NudgeMFA", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "NudgeMFA", + "value": "NudgeMFA" + } + ] + }, + { + "name": "OauthConsent", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "OauthConsent", + "value": "OauthConsent" + } + ] + }, + { + "name": "OauthConsentLowSec", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "OauthConsentLowSec", + "value": "OauthConsentLowSec" + } + ] + }, + { + "name": "OutboundSpamAlert", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "OutboundSpamAlert", + "value": "OutboundSpamAlert" + } + ] + }, + { + "name": "PasswordExpireDisabled", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "PasswordExpireDisabled", + "value": "PasswordExpireDisabled" + } + ] + }, + { + "name": "companionAppAllowedState", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "companionAppAllowedState", + "value": "companionAppAllowedState" + } + ] + }, + { + "name": "PWdisplayAppInformationRequiredState", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "PWdisplayAppInformationRequiredState", + "value": "PWdisplayAppInformationRequiredState" + } + ] + }, + { + "name": "DKIM", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "DKIM", + "value": "DKIM" + } + ] + }, + { + "name": "SecurityDefaults", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "warnBool", + "name": "SecurityDefaults", + "value": "SecurityDefaults" + } + ] + }, + { + "name": "SendFromAlias", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "bool", + "name": "SendFromAlias", + "value": "SendFromAlias" + } + ] + }, + { + "name": "SendReceiveLimit", + "StoreAs": "json", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "table", + "name": "SendReceiveLimit", + "value": "SendReceiveLimit" + } + ] + }, + { + "name": "sharingCapability", + "StoreAs": "string", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "string", + "name": "sharingCapability", + "value": "sharingCapability" + } + ] + }, + { + "name": "SpoofingWarnings", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "warnBool", + "name": "SpoofingWarnings", + "value": "SpoofingWarnings" + } + ] + }, + { + "name": "TemporaryAccessPass", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "warnBool", + "name": "TemporaryAccessPass", + "value": "TemporaryAccessPass" + } + ] + }, + { + "name": "unmanagedSync", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "warnBool", + "name": "unmanagedSync", + "value": "unmanagedSync" + } + ] + }, + { + "name": "UserSubmissionPolicy", + "StoreAs": "bool", + "UseExistingInfo": true, + "FrontendFields": [ + { + "formatter": "warnBool", + "name": "UserSubmissionPolicy", + "value": "UserSubmissionPolicy" + } + ] + } + ] +} diff --git a/Config/standards.json b/Config/standards.json new file mode 100644 index 000000000000..4ef78d3553e4 --- /dev/null +++ b/Config/standards.json @@ -0,0 +1,585 @@ +[ + { + "name": "standards.MailContacts.GeneralContact.Enabled", + "cat": "Global", + "helpText": "Receives emails about updates about subscriptions etc", + "addedComponent": { + "type": "input", + "name": "standards.MailContacts.GeneralContact.Mail", + "label": "General Contact" + }, + "label": "Set General Contact e-mail" + }, + { + "name": "standards.MailContacts.SecurityContact.Enabled", + "cat": "Global", + "helpText": "Receives emails about security alerts or advisories by Microsoft", + "addedComponent": { + "type": "input", + "name": "standards.MailContacts.SecurityContact.Mail", + "label": "Security Contact" + }, + "label": "Set Security Contact e-mail" + }, + { + "name": "standards.MailContacts.MarketingContact.Enabled", + "cat": "Global", + "helpText": "Receives the emails related to marketing; new features etc", + "addedComponent": { + "type": "input", + "name": "standards.MailContacts.MarketingContact.Mail", + "label": "Marketing Contact" + }, + "label": "Set Marketing Contact e-mail" + }, + { + "name": "standards.MailContacts.TechContact.Enabled", + "cat": "Global", + "helpText": "Receives emails related to possible technical issues, service disruptions, etc", + "addedComponent": { + "type": "input", + "name": "standards.MailContacts.TechContact.Mail", + "label": "Technical Contact" + }, + "label": "Set Technical Contact e-mail" + }, + { + "name": "standards.AuditLog", + "cat": "Global", + "helpText": "Also runs Enable-OrganizationCustomization if needed", + "addedComponent": null, + "label": "Enable the Unified Audit Log" + }, + { + "name": "standards.AnonReportDisable", + "cat": "Global", + "helpText": "", + "addedComponent": null, + "label": "Enable Usernames instead of pseudo anonymised names in reports" + }, + { + "name": "standards.DisableGuestDirectory", + "cat": "Global", + "helpText": "See the standards documentation for more information about the implications of this standard", + "addedComponent": null, + "label": "Restrict guest user access to directory objects" + }, + { + "name": "standards.DisableBasicAuthSMTP", + "cat": "Global", + "helpText": "Disables SMTP AUTH for the organization. This is the default for new tenants. Can be overridden by enabling SMTP AUTH on specific users", + "addedComponent": null, + "label": "Disable SMTP Basic Authentication" + }, + { + "name": "standards.laps", + "cat": "AAD", + "helpText": "Enables the tenant to use LAPS", + "addedComponent": null, + "label": "Enable LAPs on the tenant" + }, + { + "cat": "AAD", + "name": "standards.PWdisplayAppInformationRequiredState", + "helpText": "Enables the MS authenticator app to display information about the app that is requesting authentication", + "addedComponent": null, + "label": "Enable Passwordless with Location information and Number Matching" + }, + { + "cat": "AAD", + "name": "standards.allowOTPTokens", + "helpText": "Allows you to use MS authenticator OTP tokens", + "addedComponent": null, + "label": "Enable OTP via Authenticator." + }, + { + "cat": "AAD", + "name": "standards.allowOAuthTokens", + "helpText": "Allows you to use any OTP token generator", + "addedComponent": null, + "label": "Enable OTP Software oAuth tokens." + }, + { + "cat": "AAD", + "name": "standards.PWcompanionAppAllowedState.Enabled", + "helpText": "Sets the state of Authenticator Lite, in Outlook for mobile", + "addedComponent": { + "type": "Select", + "label": "Select value", + "name": "standards.PWcompanionAppAllowedState.state", + "values": [ + { + "label": "Enabled", + "value": "enabled" + }, + { + "label": "Disabled", + "value": "disabled" + } + ] + }, + "label": "Set Authenticator Lite state" + }, + { + "cat": "AAD", + "name": "standards.TAP.Enabled", + "helpText": "Enables TAP and sets the default TAP lifetime to 1 hour and maximum lifetime to 8 hours.", + "addedComponent": { + "type": "Select", + "label": "Select TAP Lifetime", + "name": "standards.TAP.config", + "values": [ + { + "label": "Only Once", + "value": "true" + }, + { + "label": "Multiple Logons", + "value": "false" + } + ] + }, + "label": "Enable Temporary Access Passwords" + }, + { + "cat": "AAD", + "name": "standards.SecurityDefaults", + "helpText": "Enables security defaults for the tenant. This has a lot of implications and should be carefully considered before enabling", + "addedComponent": null, + "label": "Enable Security Defaults" + }, + { + "cat": "AAD", + "name": "standards.PasswordExpireDisabled", + "helpText": "Disables the expiration of passwords for the tenant", + "addedComponent": null, + "label": "Do not expire passwords" + }, + { + "cat": "AAD", + "name": "standards.DisableSecurityGroupUsers", + "helpText": "Completely disables the creation of security groups by users. This also breaks the ability to manage groups themselves, or create Teams", + "addedComponent": null, + "label": "Disable Security Group creation by users" + }, + { + "cat": "AAD", + "name": "standards.DisableTenantCreation", + "helpText": "Restricts creation of M365 tenants to the Global Administrator or Tenant Creator roles", + "addedComponent": null, + "label": "Disable M365 Tenant creation by users" + }, + { + "cat": "AAD", + "name": "standards.OauthConsent.Enabled", + "helpText": "Disables users from being able to consent to applications, except for those specified in the field below", + "addedComponent": { + "type": "input", + "name": "standards.OauthConsent.AllowedApps", + "label": "Allowed application IDs, comma separated" + }, + "label": "Require admin consent for applications (Prevent OAuth phishing.)" + }, + { + "cat": "AAD", + "name": "standards.OauthConsentLowSec", + "helpText": "", + "label": "Allow users to consent to applications with low security risk (Prevent OAuth phishing. Lower impact, less secure.)" + }, + { + "cat": "AAD", + "name": "standards.EnableAppConsentRequests.Enabled", + "helpText": "Enables App consent admin requests for the tenant via the GA role. Does not overwrite existing reviewer settings", + "addedComponent": { + "type": "AdminRolesMultiSelect", + "label": "App Consent Reviewer Roles", + "name": "standards.EnableAppConsentRequests.ReviewerRoles" + }, + "label": "Enable App consent admin requests" + }, + { + "cat": "AAD", + "name": "standards.LegacyMFACleanup", + "helpText": "Removes legacy Per-User MFA if the tenant has Security Defaults or an All Users Conditional Access rule enabled.", + "addedComponent": null, + "label": "Remove Legacy MFA if SD or CA is active" + }, + { + "cat": "AAD", + "name": "standards.NudgeMFA.enable", + "helpText": "Enables registration campaign for the tenant", + "addedComponent": null, + "label": "Request to setup Authenticator if not setup yet." + }, + { + "cat": "AAD", + "name": "standards.NudgeMFA.disable", + "helpText": "Disables registration campaign for the tenant", + "addedComponent": null, + "label": "Disables the request to setup Authenticator if setup." + }, + { + "cat": "AAD", + "name": "standards.DisableSelfServiceLicenses", + "helpText": "This standard currently does not function and can be safely disabled", + "addedComponent": null, + "label": "Disable Self Service Licensing" + }, + { + "cat": "AAD", + "name": "standards.DisableM365GroupUsers", + "helpText": "Restricts M365 group creation to certain admin roles. This disables the ability to create Teams, Sharepoint sites, Planner, etc", + "addedComponent": null, + "label": "Disable M365 Group creation by users" + }, + { + "cat": "AAD", + "name": "standards.UndoOauth", + "helpText": "Disables App consent and set to Allow user consent for apps", + "addedComponent": null, + "label": "Undo App Consent Standard" + }, + { + "cat": "AAD", + "name": "standards.DisableGuests", + "helpText": "Blocks login for guest users that have not logged in for 90 days", + "addedComponent": null, + "label": "Disable Guest accounts that have not logged on for 90 days" + }, + { + "cat": "AAD", + "name": "standards.EnableFIDO2", + "helpText": "Enables the FIDO2 authenticationMethod for the tenant", + "addedComponent": null, + "label": "Enable FIDO2 capabilities" + }, + + { + "name": "standards.OutBoundSpamAlert.Enabled", + "cat": "Exchange", + "helpText": "Set the Outbound Spam Alert e-mail address.", + "addedComponent": { + "type": "input", + "name": "standards.OutBoundSpamAlert.OutboundSpamContact", + "label": "Outbound spam contact" + }, + "label": "Set Outbound Spam Alert e-mail" + }, + { + "name": "standards.SafeSendersDisable", + "cat": "Exchange", + "helpText": "", + "addedComponent": null, + "label": "Remove Safe Senders to prevent SPF bypass" + }, + { + "name": "standards.DisableSharedMailbox", + "cat": "Exchange", + "helpText": "Blocks login for all accounts that are marked as a shared mailbox", + "addedComponent": null, + "label": "Disable Shared Mailbox AAD accounts" + }, + { + "name": "standards.DelegateSentItems", + "cat": "Exchange", + "helpText": "Sets emails sent as and on behalf of shared mailboxes to also be stored in the shared mailbox sent items folder", + "addedComponent": null, + "label": "Set mailbox Sent Items delegation (Sent items for shared mailboxes)" + }, + { + "name": "standards.SendFromAlias", + "cat": "Exchange", + "helpText": "", + "addedComponent": null, + "label": "Allow users to send from their alias addresses" + }, + { + "name": "standards.AutoExpandArchive", + "cat": "Exchange", + "helpText": "Enables auto-expanding archives for the tenant", + "addedComponent": null, + "label": "Enable Auto-expanding archives" + }, + { + "name": "standards.SpoofWarn.enable", + "cat": "Exchange", + "helpText": "Adds indicators to e-mail messages received from external senders in Outlook. Works on all Outlook clients/OWA", + "addedComponent": null, + "label": "Enable Spoofing warnings for Outlook (This e-mail is external identifiers)" + }, + { + "name": "standards.SpoofWarn.disable", + "cat": "Exchange", + "helpText": "Disables spoof warnings from external senders in Outlook.", + "addedComponent": null, + "label": "Disable Spoofing warnings for Outlook (This e-mail is external identifiers)" + }, + { + "name": "standards.DisableViva", + "cat": "Exchange", + "helpText": "", + "addedComponent": null, + "label": "Disable daily Insight/Viva reports" + }, + { + "name": "standards.RotateDKIM", + "cat": "Exchange", + "helpText": "Rotate DKIM keys that are 1024 bit to 2048 bit", + "addedComponent": null, + "label": "Rotate DKIM keys that are 1024 bit to 2048 bit" + }, + { + "name": "standards.AddDKIM", + "cat": "Exchange", + "helpText": "Enables DKIM for all domains that currently support it", + "addedComponent": null, + "label": "Enables DKIM for all domains that currently support it" + }, + { + "name": "standards.ActivityBasedTimeout", + "cat": "Global", + "helpText": "Enables and sets Idle session timeout for Microsoft 365 to 1 hour. This policy affects most M365 web apps", + "addedComponent": null, + "label": "Enable 1 hour Activity based Timeout" + }, + { + "name": "standards.SendReceiveLimitTenant.Enabled", + "cat": "Exchange", + "helpText": "Sets the Send and Receive limits for new users. Valid values are 1KB to 150MB. Invalid values will be set to EXO standard of 35MB,36MB", + "addedComponent": { + "type": "input", + "name": "standards.SendReceiveLimitTenant.SendReceiveLimit", + "label": "Send limit and Receive limit, comma separated" + }, + "label": "Set send/receive size limits" + }, + + { + "name": "standards.calDefault.Enabled", + "cat": "Exchange", + "helpText": "Sets the default sharing level for the default calendar, for all users", + "addedComponent": { + "type": "Select", + "label": "Select Sharing Level", + "name": "standards.calDefault.permissionlevel", + "values": [ + { + "label": "Owner - The user can create, read, edit, and delete all items in the folder, and create subfolders. The user is both folder owner and folder contact.", + "value": "Owner" + }, + { + "label": "Publishing Editor - The user can create, read, edit, and delete all items in the folder, and create subfolders.", + "value": "PublishingEditor" + }, + { + "label": "Reviewer - The user can read all items in the folder.", + "value": "Reviewer" + }, + { + "label": "Editor - The user can create items in the folder. The contents of the folder do not appear.", + "value": "Contributor" + }, + { + "label": "Limited Details - The user can view free/busy time within the calendar and the subject and location of appointments.", + "value": "LimitedDetails" + }, + { + "label": "Availability Only - Indicates that the user can view only free/busy time within the calendar.", + "value": "AvailabilityOnly" + }, + { + "label": "None - The user has no permissions on the folder.", + "value": "none" + } + ] + }, + "label": "Set Sharing Level for Default calendar" + }, + { + "name": "standards.UserSubmissions.enable", + "cat": "Exchange", + "helpText": "", + "addedComponent": null, + "label": "Enable the built-in Report button in Outlook" + }, + { + "name": "standards.UserSubmissions.disable", + "cat": "Exchange", + "helpText": "", + "addedComponent": null, + "label": "Disable the built-in Report button in Outlook" + }, + { + "name": "standards.intuneDeviceReg.Enabled", + "cat": "Intune", + "helpText": "", + "addedComponent": { + "type": "input", + "name": "standards.intuneDeviceReg.max", + "label": "Maximum devices (Enter 2147483647 for unlimited.)" + }, + "label": "Set Maximum Number of Devices per user" + }, + { + "name": "standards.intuneDeviceRetirementDays.Enabled", + "cat": "Intune", + "helpText": "A value between 0 and 270 is supported. A value of 0 disables retirement.", + "addedComponent": { + "type": "input", + "name": "standards.intuneDeviceRetirementDays.days", + "label": "Maximum days (0 equals disabled)" + }, + "label": "Set inactive device retirement days" + }, + { + "name": "standards.intuneRequireMFA", + "cat": "Intune", + "helpText": "", + "label": "Require Multifactor Authentication to register or join devices with Microsoft Entra" + }, + { + "name": "standards.sharingCapability.Enabled", + "cat": "SharePoint", + "helpText": "Sets the default sharing level for OneDrive and Sharepoint. This is a tenant wide setting and overrules any settings set on the site level", + "addedComponent": { + "type": "Select", + "label": "Select Sharing Level", + "name": "standards.sharingCapability.Level", + "values": [ + { + "label": "Users can share only with people in the organization. No external sharing is allowed.", + "value": "disabled" + }, + { + "label": "Users can share with new and existing guests. Guests must sign in or provide a verification code.", + "value": "externalUserSharingOnly" + }, + { + "label": "Users can share with anyone by using links that do not require sign-in.", + "value": "externalUserAndGuestSharing" + }, + { + "label": "Users can share with existing guests (those already in the directory of the organization).", + "value": "existingExternalUserSharingOnly" + } + ] + }, + "label": "Set Sharing Level for OneDrive and Sharepoint" + }, + { + "name": "standards.ExcludedfileExt.Enabled", + "cat": "SharePoint", + "helpText": "", + "addedComponent": { + "type": "input", + "name": "standards.ExcludedfileExt.ext", + "label": "Extensions, Comma separated" + }, + "label": "Exclude File Extensions from Syncing" + }, + { + "name": "standards.disableMacSync", + "cat": "SharePoint", + "helpText": "", + "addedComponent": null, + "label": "Do not allow Mac devices to sync using OneDrive" + }, + { + "name": "standards.DisableReshare", + "cat": "SharePoint", + "helpText": "Disables the ability for external users to share files they don't own. Sharing links can only be made for People with existing access", + "addedComponent": null, + "label": "Disable Resharing by External Users" + }, + { + "name": "standards.DeletedUserRentention", + "cat": "SharePoint", + "helpText": "Sets the retention period for deleted users OneDrive to 1 year/365 days", + "addedComponent": null, + "label": "Retain a deleted user OneDrive for 1 year" + }, + { + "name": "standards.DisableUserSiteCreate", + "cat": "SharePoint", + "helpText": "Disables users from creating new SharePoint sites", + "addedComponent": null, + "label": "Disable site creation by standard users" + }, + { + "name": "standards.unmanagedSync", + "cat": "SharePoint", + "helpText": "", + "addedComponent": null, + "label": "Only allow users to sync OneDrive from AAD joined devices" + }, + { + "name": "standards.DisableAddShortcutsToOneDrive", + "cat": "SharePoint", + "helpText": "When the feature is disabled the option Add shortcut to My files will be removed; any folders that have already been added will remain on the user's computer.", + "addedComponent": null, + "label": "Disable Add Shortcuts To OneDrive" + }, + { + "name": "standards.IntuneTemplate.enabled", + "cat": "templates", + "helpText": "", + "addedComponent": null, + "label": "Intune Templates" + }, + { + "name": "standards.GroupTemplate.enabled", + "cat": "templates", + "helpText": "", + "addedComponent": null, + "label": "Group Templates" + }, + { + "name": "standards.ExConnector.enabled", + "cat": "templates", + "helpText": "", + "addedComponent": null, + "label": "Exchange Connector Templates" + }, + { + "name": "standards.ConditionalAccess.enabled", + "cat": "templates", + "helpText": "", + "addedComponent": null, + "label": "Conditional Access Templates" + }, + { + "name": "standards.TransportRuleTemplate.enabled", + "cat": "templates", + "helpText": "", + "addedComponent": null, + "label": "Transport Rule Templates" + }, + { + "name": "standards.ModernAuth", + "cat": "legacy", + "helpText": "Modern Authentication is enabled by default. This standard is no longer required and can be safely disabled", + "addedComponent": null, + "label": "Enable Modern Authentication" + }, + { + "name": "standards.DisableBasicAuth", + "cat": "legacy", + "helpText": "Basic Authentication is disabled by default. This standard is no longer required and can be safely disabled", + "addedComponent": null, + "label": "Disable Basic Authentication" + }, + { + "name": "standards.PWnumberMatchingRequiredState", + "cat": "legacy", + "helpText": "Passwordless with number matching is now enabled by default. This standard is no longer required and can be safely disabled", + "addedComponent": null, + "label": "Enable Passwordless with Number Matching" + }, + { + "cat": "legacy", + "name": "standards.LegacyMFA", + "helpText": "This standard is no longer works and can be safely disabled", + "addedComponent": null, + "label": "Enable per-user MFA for all user (Legacy, Requires DAP.)" + } +] diff --git a/ExecExtensionNinjaOneQueue/run.ps1 b/ExecExtensionNinjaOneQueue/run.ps1 index bcb1695ae15b..21720a79b6a5 100644 --- a/ExecExtensionNinjaOneQueue/run.ps1 +++ b/ExecExtensionNinjaOneQueue/run.ps1 @@ -9,4 +9,5 @@ Switch ($QueueItem.NinjaAction) { 'StartAutoMapping' { Invoke-NinjaOneOrgMapping } 'AutoMapTenant' { Invoke-NinjaOneOrgMappingTenant -QueueItem $QueueItem } 'SyncTenant' { Invoke-NinjaOneTenantSync -QueueItem $QueueItem } + 'SyncTenants' {Invoke-NinjaOneSync} } diff --git a/ExecGDAPInviteApproved_Timer/function.json b/ExecGDAPInviteApproved_Timer/function.json index 6b68992375e9..32b454a2a015 100644 --- a/ExecGDAPInviteApproved_Timer/function.json +++ b/ExecGDAPInviteApproved_Timer/function.json @@ -9,7 +9,7 @@ { "type": "queue", "direction": "out", - "name": "Msg", + "name": "gdapinvitequeue", "queueName": "gdapinvitequeue" } ] diff --git a/ExecGDAPInviteQueue/run.ps1 b/ExecGDAPInviteQueue/run.ps1 index 78e43c118449..1b95a443bab0 100644 --- a/ExecGDAPInviteQueue/run.ps1 +++ b/ExecGDAPInviteQueue/run.ps1 @@ -2,34 +2,6 @@ param( $QueueItem, $TriggerMetadata) # Write out the queue message and metadata to the information log. -Write-Host "PowerShell queue trigger function processed work item: $QueueItem" -#$TenantFilter = $env:TenantID +Write-Host "PowerShell queue trigger function processed work item: $($QueueItem.customer.displayName)" -$Table = Get-CIPPTable -TableName 'GDAPInvites' -$Invite = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$QueueItem'" -$APINAME = 'GDAPInvites' -$RoleMappings = $Invite.RoleMappings | ConvertFrom-Json -Write-Host ($Invite | ConvertTo-Json -Compress) - -foreach ($role in $RoleMappings) { - try { - $Mappingbody = ConvertTo-Json -Depth 10 -InputObject @{ - 'accessContainer' = @{ - 'accessContainerId' = "$($Role.GroupId)" - 'accessContainerType' = 'securityGroup' - } - 'accessDetails' = @{ - 'unifiedRoles' = @(@{ - 'roleDefinitionId' = "$($Role.roleDefinitionId)" - }) - } - } - New-GraphPostRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($QueueItem)/accessAssignments" -tenantid $env:TenantID -type POST -body $MappingBody -verbose - Start-Sleep -Milliseconds 100 - } catch { - Write-LogMessage -API $APINAME -message "GDAP Group mapping failed - $($role.GroupId): $($_.Exception.Message)" -Sev Error - exit 1 - } - Write-LogMessage -API $APINAME -message "Groups mapped for GDAP Relationship: $($GdapInvite.RowKey)" -Sev Info -} -Remove-AzDataTableEntity @Table -Entity $Invite +Set-CIPPGDAPInviteGroups -Relationship $QueueItem \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 index ee53c68020d8..6f03e28b64e2 100644 --- a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 @@ -10,9 +10,8 @@ function Add-CIPPAzDataTableEntity { foreach ($SingleEnt in $Entity) { try { Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt - } - catch [System.Exception] { - if ($_.Exception.ErrorCode -eq "PropertyValueTooLarge" -or $_.Exception.ErrorCode -eq "EntityTooLarge") { + } catch [System.Exception] { + if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge') { try { $MaxSize = 30kb $largePropertyName = $null @@ -36,10 +35,10 @@ function Add-CIPPAzDataTableEntity { } $splitInfo = @{ - OriginalHeader = $largePropertyName; + OriginalHeader = $largePropertyName SplitHeaders = $splitPropertyNames } - $SingleEnt["SplitOverProps"] = ($splitInfo | ConvertTo-Json).ToString() + $SingleEnt['SplitOverProps'] = ($splitInfo | ConvertTo-Json).ToString() $SingleEnt.Remove($largePropertyName) for ($i = 0; $i -lt $splitData.Count; $i++) { @@ -49,12 +48,10 @@ function Add-CIPPAzDataTableEntity { Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt } - } - catch { + } catch { throw "Error processing entity: $($_.Exception.Message)." } - } - else { + } else { throw $_ } } diff --git a/Modules/CIPPCore/Public/Add-CIPPBPAField.ps1 b/Modules/CIPPCore/Public/Add-CIPPBPAField.ps1 new file mode 100644 index 000000000000..1dd0b8c9d867 --- /dev/null +++ b/Modules/CIPPCore/Public/Add-CIPPBPAField.ps1 @@ -0,0 +1,45 @@ +function Add-CIPPBPAField { + param ( + $BPAName = 'CIPP Standards v1.0 - Table view', + $FieldName, + $FieldValue, + $StoreAs, + $Tenant + ) + $Table = Get-CippTable -tablename 'cachebpav2' + $TenantName = Get-Tenants | Where-Object -Property defaultDomainName -EQ $Tenant + $CurrentContentsObject = (Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$BPAName' and PartitionKey eq '$($TenantName.customerId)'") + Write-Host "Adding $FieldName to $BPAName for $Tenant. content is $($CurrentContents.RowKey)" + if ($CurrentContentsObject.RowKey) { + $CurrentContents = @{} + $CurrentContentsObject.PSObject.Properties | ForEach-Object { + $CurrentContents[$_.Name] = $_.Value + } + $Result = $CurrentContents + } else { + $Result = @{ + Tenant = "$($TenantName.displayName)" + GUID = "$($TenantName.customerId)" + RowKey = $BPAName + PartitionKey = "$($TenantName.customerId)" + LastRefresh = [string]$(Get-Date (Get-Date).ToUniversalTime() -UFormat '+%Y-%m-%dT%H:%M:%S.000Z') + } + } + switch -Wildcard ($StoreAs) { + '*bool' { + $Result["$fieldName"] = [bool]$FieldValue + } + 'JSON' { + + if ($FieldValue -eq $null) { $JsonString = '{}' } else { $JsonString = (ConvertTo-Json -Depth 15 -InputObject $FieldValue -Compress) } + $Result[$fieldName] = [string]$JsonString + } + 'string' { + $Result[$fieldName], [string]$FieldValue + } + 'percentage' { + + } + } + Add-CIPPAzDataTableEntity @Table -Entity $Result -Force +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAPDevice.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAPDevice.ps1 index be59d3c44b89..262bb17f79bc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAPDevice.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAPDevice.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddAPDevice { +Function Invoke-AddAPDevice { <# .FUNCTIONALITY Entrypoint @@ -8,43 +8,43 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." -$TenantFilter = (Get-Tenants | Where-Object { $_.defaultDomainName -eq $Request.body.TenantFilter }).customerId -$GroupName = if ($Request.body.Groupname) { $Request.body.Groupname } else { (New-Guid).GUID } -$rawDevices = $request.body.autopilotData -$Devices = ConvertTo-Json @($rawDevices) -Write-Host $Devices -$Result = try { - $CurrentStatus = (New-GraphgetRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$tenantfilter/DeviceBatches" -scope 'https://api.partnercenter.microsoft.com/user_impersonation') - if ($groupname -in $CurrentStatus.items.id) { throw "This device batch name already exists. Please try with another name." } - $body = '{"batchId":"' + $($GroupName) + '","devices":' + $Devices + '}' - $GraphRequest = (New-GraphPostRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$TenantFilter/DeviceBatches" -body $body -scope 'https://api.partnercenter.microsoft.com/user_impersonation') - Write-Host ($GraphRequest | ConvertTo-Json) - Start-Sleep 5 - $NewStatus = New-GraphgetRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$tenantfilter/DeviceBatches" -scope 'https://api.partnercenter.microsoft.com/user_impersonation' - Write-Host $($Newstatus | ConvertTo-Json) - if ($Newstatus.totalcount -eq $CurrentStatus.totalcount) { throw "We could not find the new autopilot device. Please check if your input is correct." } - Write-Host $CurrentStatus.Items - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($Request.body.TenantFilter) -message "Created Autopilot devices group. Group ID is $GroupName" -Sev "Info" - "Created Autopilot devices group for $($Request.body.TenantFilter). Group ID is $GroupName" -} -catch { - "$($Request.body.TenantFilter): Failed to create autopilot devices. $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($Request.body.TenantFilter) -message "Failed to create autopilot devices. $($_.Exception.Message)" -Sev "Error" -} + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + $TenantFilter = (Get-Tenants | Where-Object { $_.defaultDomainName -eq $Request.body.TenantFilter }).customerId + $GroupName = if ($Request.body.Groupname) { $Request.body.Groupname } else { (New-Guid).GUID } + $rawDevices = $request.body.autopilotData + $Devices = ConvertTo-Json @($rawDevices) + Write-Host $Devices + $Result = try { + $CurrentStatus = (New-GraphgetRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$tenantfilter/DeviceBatches" -scope 'https://api.partnercenter.microsoft.com/user_impersonation') + if ($groupname -in $CurrentStatus.items.id) { throw 'This device batch name already exists. Please try with another name.' } + $body = '{"batchId":"' + $($GroupName) + '","devices":' + $Devices + '}' + $GraphRequest = (New-GraphPostRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$TenantFilter/DeviceBatches" -body $body -scope 'https://api.partnercenter.microsoft.com/user_impersonation') + Write-Host ($GraphRequest | ConvertTo-Json) + Start-Sleep 5 + $NewStatus = New-GraphgetRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$tenantfilter/DeviceBatches" -scope 'https://api.partnercenter.microsoft.com/user_impersonation' + Write-Host $($Newstatus | ConvertTo-Json) + if ($Newstatus.totalcount -eq $CurrentStatus.totalcount) { throw 'We could not find the new autopilot device. Please check if your input is correct.' } + Write-Host $CurrentStatus.Items + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($Request.body.TenantFilter) -message "Created Autopilot devices group. Group ID is $GroupName" -Sev 'Info' + "Created Autopilot devices group for $($Request.body.TenantFilter). Group ID is $GroupName" + } + catch { + "$($Request.body.TenantFilter): Failed to create autopilot devices. $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($Request.body.TenantFilter) -message "Failed to create autopilot devices. $($_.Exception.Message)" -Sev 'Error' + } -$body = [pscustomobject]@{"Results" = $Result } -Write-Host $body -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + $body = [pscustomobject]@{'Results' = $Result } + Write-Host $body + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body - }) + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAlert.ps1 index 25740fc87531..475147d04df3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAlert.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAlert.ps1 @@ -15,7 +15,8 @@ Function Invoke-AddAlert { try { $TenantID = if ($tenant -ne 'AllTenants') { (get-tenants | Where-Object -Property defaultDomainName -EQ $Tenant).customerId - } else { + } + else { 'AllTenants' } if ($Request.body.SetAlerts) { @@ -64,7 +65,8 @@ Function Invoke-AddAlert { Push-OutputBinding -Name Subscription -Value $Params } } - } else { + } + else { foreach ($eventType in $Request.body.EventTypes.value) { $params = @{ TenantFilter = $tenant @@ -80,7 +82,8 @@ Function Invoke-AddAlert { } "Successfully added Alert for $($Tenant) to queue." Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Successfully added Alert for $($Tenant) to queue." -Sev 'Info' - } catch { + } + catch { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed to add Alert for for $($Tenant) to queue" -Sev 'Error' "Failed to add Alert for for $($Tenant) to queue $($_.Exception.message)" } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAutopilotConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAutopilotConfig.ps1 index f850042fc7d2..96208b3674f8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAutopilotConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddAutopilotConfig.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddAutopilotConfig { +Function Invoke-AddAutopilotConfig { <# .FUNCTIONALITY Entrypoint @@ -8,70 +8,33 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' -# Input bindings are passed in via param block. -$user = $request.headers.'x-ms-client-principal' -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -$displayname = $request.body.Displayname -$description = $request.body.Description -$AssignTo = if ($request.body.Assignto -ne "on") { $request.body.Assignto } -$Profbod = $Request.body -$usertype = if ($Profbod.NotLocalAdmin -eq "true") { "standard" } else { "administrator" } -$DeploymentMode = if ($profbod.DeploymentMode -eq "true") { "shared" } else { "singleUser" } -$results = foreach ($Tenant in $tenants) { - try { - $ObjBody = [pscustomobject]@{ - "@odata.type" = "#microsoft.graph.azureADWindowsAutopilotDeploymentProfile" - "displayName" = "$($displayname)" - "description" = "$($description)" - "deviceNameTemplate" = "$($profbod.DeviceNameTemplate)" - "language" = "os-default" - "enableWhiteGlove" = $([bool]($profbod.allowWhiteGlove)) - "deviceType" = "windowsPc" - "extractHardwareHash" = $([bool]($profbod.CollectHash)) - "roleScopeTagIds" = @() - "hybridAzureADJoinSkipConnectivityCheck" = $false - "outOfBoxExperienceSettings" = @{ - "deviceUsageType" = "$DeploymentMode" - "hideEscapeLink" = $([bool]($Profbod.hideChangeAccount)) - "hidePrivacySettings" = $([bool]($Profbod.hidePrivacy)) - "hideEULA" = $([bool]($Profbod.hideTerms)) - "userType" = "$usertype" - "skipKeyboardSelectionPage" = $([bool]($Profbod.Autokeyboard)) - } - } - $Body = ConvertTo-Json -InputObject $ObjBody - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeploymentProfiles" -body $body -tenantid $Tenant - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Added Autopilot profile $($Displayname)" -Sev "Info" - if ($AssignTo) { - $AssignBody = '{"target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}}' - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeploymentProfiles/$($GraphRequest.id)/assignments" -tenantid $Tenant -type POST -body $AssignBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Assigned autopilot profile $($Displayname) to $AssignTo" -Sev "Info" - } - "Successfully added profile for $($Tenant)" + # Input bindings are passed in via param block. + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $displayname = $request.body.Displayname + $description = $request.body.Description + $AssignTo = if ($request.body.Assignto -ne 'on') { $request.body.Assignto } + $Profbod = $Request.body + $usertype = if ($Profbod.NotLocalAdmin -eq 'true') { 'standard' } else { 'administrator' } + $DeploymentMode = if ($profbod.DeploymentMode -eq 'true') { 'shared' } else { 'singleUser' } + $results = foreach ($Tenant in $tenants) { + Set-CIPPDefaultAPDeploymentProfile -tenantFilter $tenant -displayname $displayname -description $description -usertype $usertype -DeploymentMode $DeploymentMode -assignto $AssignTo -devicenameTemplate $Profbod.deviceNameTemplate -allowWhiteGlove $Profbod.allowWhiteGlove -CollectHash $Profbod.collectHash -hideChangeAccount $Profbod.hideChangeAccount -hidePrivacy $Profbod.hidePrivacy -hideTerms $Profbod.hideTerms -Autokeyboard $Profbod.Autokeyboard } - catch { - "Failed to add profile for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Failed adding Autopilot Profile $($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue - } - -} -$body = [pscustomobject]@{"Results" = $results } + $body = [pscustomobject]@{'Results' = $results } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCAPolicy.ps1 index ab0fcfffb7d3..ab6635459e4b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCAPolicy.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddCAPolicy { +Function Invoke-AddCAPolicy { <# .FUNCTIONALITY Entrypoint @@ -8,32 +8,32 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -if ("AllTenants" -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } -$results = foreach ($Tenant in $tenants) { - try { - $CAPolicy = New-CIPPCAPolicy -TenantFilter $tenant -state $request.body.NewState -RawJSON $Request.body.RawJSON -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added Conditional Access Policy $($Displayname)" -Sev "Error" - "Successfully added Conditional Access Policy for $($Tenant)" - } - catch { - "Failed to add policy for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed adding Conditional Access Policy $($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue - } + $results = foreach ($Tenant in $tenants) { + try { + $CAPolicy = New-CIPPCAPolicy -TenantFilter $tenant -state $request.body.NewState -RawJSON $Request.body.RawJSON -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added Conditional Access Policy $($Displayname)" -Sev 'Info' + "Successfully added Conditional Access Policy for $($Tenant)" + } + catch { + "Failed to add policy for $($Tenant): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed to add Conditional Access Policy $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + continue + } -} + } -$body = [pscustomobject]@{"Results" = @($results) } + $body = [pscustomobject]@{'Results' = @($results) } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCATemplate.ps1 index 9fcd305891ba..9c5d7ee1261e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCATemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddCATemplate.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddCATemplate { +Function Invoke-AddCATemplate { <# .FUNCTIONALITY Entrypoint @@ -8,65 +8,65 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$TenantFilter = $Request.Query.TenantFilter -try { - $GUID = (New-Guid).GUID - $JSON = if ($request.body.rawjson) { - ([pscustomobject]$request.body.rawjson) | ConvertFrom-Json - } - else { + $TenantFilter = $Request.Query.TenantFilter + try { + $GUID = (New-Guid).GUID + $JSON = if ($request.body.rawjson) { + ([pscustomobject]$request.body.rawjson) | ConvertFrom-Json + } + else { ([pscustomobject]$Request.body) | ForEach-Object { - $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name - $_ | Select-Object -Property $NonEmptyProperties + $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name + $_ | Select-Object -Property $NonEmptyProperties + } } - } - - $includelocations = New-Object System.Collections.ArrayList - $IncludeJSON = foreach ($Location in $JSON.conditions.locations.includeLocations) { - $locationinfo = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations" -tenantid $TenantFilter | Where-Object -Property id -EQ $location | Select-Object * -ExcludeProperty id, *time* - $null = if ($locationinfo) { $includelocations.add($locationinfo.displayName) } else { $includelocations.add($location) } - $locationinfo - } - if ($includelocations) { $JSON.conditions.locations.includeLocations = $includelocations } + $includelocations = New-Object System.Collections.ArrayList + $IncludeJSON = foreach ($Location in $JSON.conditions.locations.includeLocations) { + $locationinfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -tenantid $TenantFilter | Where-Object -Property id -EQ $location | Select-Object * -ExcludeProperty id, *time* + $null = if ($locationinfo) { $includelocations.add($locationinfo.displayName) } else { $includelocations.add($location) } + $locationinfo + } + if ($includelocations) { $JSON.conditions.locations.includeLocations = $includelocations } - $excludelocations = New-Object System.Collections.ArrayList - $ExcludeJSON = foreach ($Location in $JSON.conditions.locations.excludeLocations) { - $locationinfo = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations" -tenantid $TenantFilter | Where-Object -Property id -EQ $location | Select-Object * -ExcludeProperty id, *time* - $null = if ($locationinfo) { $excludelocations.add($locationinfo.displayName) } else { $excludelocations.add($location) } - $locationinfo - } - if ($excludelocations) { $JSON.conditions.locations.excludeLocations = $excludelocations } + $excludelocations = New-Object System.Collections.ArrayList + $ExcludeJSON = foreach ($Location in $JSON.conditions.locations.excludeLocations) { + $locationinfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -tenantid $TenantFilter | Where-Object -Property id -EQ $location | Select-Object * -ExcludeProperty id, *time* + $null = if ($locationinfo) { $excludelocations.add($locationinfo.displayName) } else { $excludelocations.add($location) } + $locationinfo + } - $JSON | Add-Member -NotePropertyName 'LocationInfo' -NotePropertyValue @($IncludeJSON, $ExcludeJSON) + if ($excludelocations) { $JSON.conditions.locations.excludeLocations = $excludelocations } - $JSON = ($JSON | ConvertTo-Json -Depth 100) - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$JSON" - RowKey = "$GUID" - PartitionKey = "CATemplate" - GUID = "$GUID" - } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Transport Rule Template $($Request.body.name) with GUID $GUID" -Sev "Debug" - $body = [pscustomobject]@{"Results" = "Successfully added template" } + $JSON | Add-Member -NotePropertyName 'LocationInfo' -NotePropertyValue @($IncludeJSON, $ExcludeJSON) + + $JSON = ($JSON | ConvertTo-Json -Depth 100) + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$JSON" + RowKey = "$GUID" + PartitionKey = 'CATemplate' + GUID = "$GUID" + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Transport Rule Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' + $body = [pscustomobject]@{'Results' = 'Successfully added template' } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Transport Rule Template: $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Intune Template Deployment failed: $($_.Exception.Message)" } -} + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Transport Rule Template: $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Intune Template Deployment failed: $($_.Exception.Message)" } + } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddChocoApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddChocoApp.ps1 index 033f7a909a6a..d469e507a5db 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddChocoApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddChocoApp.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddChocoApp { +Function Invoke-AddChocoApp { <# .FUNCTIONALITY Entrypoint @@ -8,57 +8,56 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -Write-Host "PowerShell HTTP trigger function processed a request." -$ChocoApp = $request.body -$intuneBody = Get-Content "AddChocoApp\choco.app.json" | ConvertFrom-Json -$assignTo = $Request.body.AssignTo -$intuneBody.description = $ChocoApp.description -$intuneBody.displayName = $chocoapp.ApplicationName -$intuneBody.installExperience.runAsAccount = if ($ChocoApp.InstallAsSystem) { "system" } else { "user" } -$intuneBody.installExperience.deviceRestartBehavior = if ($ChocoApp.DisableRestart) { "suppress" } else { "allow" } -$intuneBody.installCommandLine = "powershell.exe -executionpolicy bypass .\Install.ps1 -InstallChoco -Packagename $($chocoapp.PackageName)" -if ($ChocoApp.customrepo) { - $intuneBody.installCommandLine = $intuneBody.installCommandLine + " -CustomRepo $($chocoapp.CustomRepo)" -} -$intuneBody.UninstallCommandLine = "powershell.exe -executionpolicy bypass .\Uninstall.ps1 -Packagename $($chocoapp.PackageName)" -$intunebody.detectionRules[0].path = "$($ENV:SystemDrive)\programdata\chocolatey\lib" -$intunebody.detectionRules[0].fileOrFolderName = "$($chocoapp.PackageName)" + Write-Host 'PowerShell HTTP trigger function processed a request.' + $ChocoApp = $request.body + $intuneBody = Get-Content 'AddChocoApp\choco.app.json' | ConvertFrom-Json + $assignTo = $Request.body.AssignTo + $intuneBody.description = $ChocoApp.description + $intuneBody.displayName = $chocoapp.ApplicationName + $intuneBody.installExperience.runAsAccount = if ($ChocoApp.InstallAsSystem) { 'system' } else { 'user' } + $intuneBody.installExperience.deviceRestartBehavior = if ($ChocoApp.DisableRestart) { 'suppress' } else { 'allow' } + $intuneBody.installCommandLine = "powershell.exe -executionpolicy bypass .\Install.ps1 -InstallChoco -Packagename $($chocoapp.PackageName)" + if ($ChocoApp.customrepo) { + $intuneBody.installCommandLine = $intuneBody.installCommandLine + " -CustomRepo $($chocoapp.CustomRepo)" + } + $intuneBody.UninstallCommandLine = "powershell.exe -executionpolicy bypass .\Uninstall.ps1 -Packagename $($chocoapp.PackageName)" + $intunebody.detectionRules[0].path = "$($ENV:SystemDrive)\programdata\chocolatey\lib" + $intunebody.detectionRules[0].fileOrFolderName = "$($chocoapp.PackageName)" -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -$Results = foreach ($Tenant in $tenants) { - try { - $CompleteObject = [PSCustomObject]@{ - tenant = $tenant - Applicationname = $ChocoApp.ApplicationName - assignTo = $assignTo - InstallationIntent = $request.body.InstallationIntent - IntuneBody = $intunebody - } | ConvertTo-Json -Depth 15 - $Table = Get-CippTable -tablename 'apps' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$CompleteObject" - RowKey = "$((New-Guid).GUID)" - PartitionKey = "apps" + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $Results = foreach ($Tenant in $tenants) { + try { + $CompleteObject = [PSCustomObject]@{ + tenant = $tenant + Applicationname = $ChocoApp.ApplicationName + assignTo = $assignTo + InstallationIntent = $request.body.InstallationIntent + IntuneBody = $intunebody + } | ConvertTo-Json -Depth 15 + $Table = Get-CippTable -tablename 'apps' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$CompleteObject" + RowKey = "$((New-Guid).GUID)" + PartitionKey = 'apps' + } + "Successfully added Choco App for $($Tenant) to queue." + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Chocolatey Application $($intunebody.Displayname) queued to add" -Sev 'Info' + } + catch { + "Failed adding Choco App for $($Tenant) to queue" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed to add Chocolatey Application $($intunebody.Displayname) to queue" -Sev 'Error' } - "Successfully added Choco App for $($Tenant) to queue." - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Chocolatey Application $($intunebody.Displayname) queued to add" -Sev "Info" - } - catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed to add Chocolatey Application $($intunebody.Displayname) to queue" -Sev "Error" - "Failed added Choco App for $($Tenant) to queue" } -} - -$body = [pscustomobject]@{"Results" = $results } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + $body = [pscustomobject]@{'Results' = $results } - } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddContact.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddContact.ps1 index 1c4f2963635d..ebd0d9be935b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddContact.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddContact.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddContact { +Function Invoke-AddContact { <# .FUNCTIONALITY Entrypoint @@ -8,41 +8,40 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$contactobj = $Request.body -$user = $request.headers.'x-ms-client-principal' + $contactobj = $Request.body -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." -try { + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + try { - $BodyToship = [pscustomobject] @{ - "displayName" = $contactobj.Displayname - "name" = $contactobj.displayName - "ExternalEmailAddress" = $contactobj.Email - FirstName = $contactObj.firstname - lastname = $contactobj.lastname + $BodyToship = [pscustomobject] @{ + 'displayName' = $contactobj.Displayname + 'name' = $contactobj.displayName + 'ExternalEmailAddress' = $contactobj.Email + FirstName = $contactObj.firstname + lastname = $contactobj.lastname - } - $NewContact = New-ExoRequest -tenantid $Request.body.tenantid -cmdlet "New-MailContact" -cmdparams $BodyToship -UseSystemMailbox $true - Write-Host ( $NewContact | ConvertTo-Json) - New-ExoRequest -tenantid $Request.body.tenantid -cmdlet "Set-MailContact" -cmdparams @{identity = $NewContact.id; HiddenFromAddressListsEnabled = [boolean]$contactobj.hidefromGAL } -UseSystemMailbox $true - $body = [pscustomobject]@{"Results" = "Successfully added a contact." } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($contactobj.tenantid) -message "Created contact $($contactobj.displayname) with id $($GraphRequest.id) for " -Sev "Info" + } + $NewContact = New-ExoRequest -tenantid $Request.body.tenantid -cmdlet 'New-MailContact' -cmdparams $BodyToship -UseSystemMailbox $true + Write-Host ( $NewContact | ConvertTo-Json) + New-ExoRequest -tenantid $Request.body.tenantid -cmdlet 'Set-MailContact' -cmdparams @{identity = $NewContact.id; HiddenFromAddressListsEnabled = [boolean]$contactobj.hidefromGAL } -UseSystemMailbox $true + $body = [pscustomobject]@{'Results' = 'Successfully added a contact.' } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($contactobj.tenantid) -message "Created contact $($contactobj.displayname) with id $($GraphRequest.id) for " -Sev 'Info' -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($contactobj.tenantid) -message "contact creation API failed. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to create contact. $($_.Exception.Message)" } + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($contactobj.tenantid) -message "Contact creation API failed. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to create contact. $($_.Exception.Message)" } -} + } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddDefenderDeployment.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddDefenderDeployment.ps1 index 8d2fcc9113b3..e38a8fd67769 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddDefenderDeployment.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddDefenderDeployment.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddDefenderDeployment { +Function Invoke-AddDefenderDeployment { <# .FUNCTIONALITY Entrypoint @@ -8,237 +8,237 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$Tenants = ($Request.body.selectedTenants).defaultDomainName -if ("AllTenants" -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } -$Compliance = $request.body.Compliance -$PolicySettings = $request.body.Policy -$ASR = $request.body.ASR -$EDR = $request.body.EDR -$results = foreach ($Tenant in $tenants) { - try { - $SettingsObj = @{ - id = 'fc780465-2017-40d4-a0c5-307022471b92' - androidEnabled = [bool]$Compliance.ConnectAndroid - iosEnabled = [bool]$Compliance.ConnectIos - windowsEnabled = [bool]$Compliance.Connectwindows - macEnabled = [bool]$Compliance.ConnectMac - partnerUnsupportedOsVersionBlocked = [bool]$Compliance.BlockunsupportedOS - partnerUnresponsivenessThresholdInDays = 7 - allowPartnerToCollectIOSApplicationMetadata = [bool]$Compliance.ConnectIosCompliance - allowPartnerToCollectIOSPersonalApplicationMetadata = [bool]$Compliance.ConnectIosCompliance - androidMobileApplicationManagementEnabled = [bool]$Compliance.ConnectAndroidCompliance - iosMobileApplicationManagementEnabled = [bool]$Compliance.appSync - microsoftDefenderForEndpointAttachEnabled = [bool]$compliance.AllowMEMEnforceCompliance - } | ConvertTo-Json -Compress - $SettingsRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/" -tenantid $tenant -type POST -body $SettingsObj - "$($Tenant): Successfully set Defender Compliance and Reporting settings" - - $Settings = switch ($PolicySettings) { - { $_.ScanArchives } { - @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowarchivescanning'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowarchivescanning_1'; settingValueTemplateReference = @{settingValueTemplateId = '9ead75d4-6f30-4bc5-8cc5-ab0f999d79f0' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '7c5c9cde-f74d-4d11-904f-de4c27f72d89' } } } - } { $_.AllowBehavior } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowbehaviormonitoring' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowbehaviormonitoring_1'; settingValueTemplateReference = @{settingValueTemplateId = '905921da-95e2-4a10-9e30-fe5540002ce1' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '8eef615a-1aa0-46f4-a25a-12cbe65de5ab' } } } - } { $_.AllowCloudProtection } { - @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowcloudprotection'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowcloudprotection_1'; settingValueTemplateReference = @{settingValueTemplateId = '16fe8afd-67be-4c50-8619-d535451a500c' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '7da139f1-9b7e-407d-853a-c2e5037cdc70' } } } - } { $_.AllowEmailScanning } { - @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowemailscanning' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowemailscanning_1'; settingValueTemplateReference = @{settingValueTemplateId = 'fdf107fd-e13b-4507-9d8f-db4d93476af9' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'b0d9ee81-de6a-4750-86d7-9397961c9852' } } } - } { $_.AllowFullScanNetwork } { - @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowfullscanonmappednetworkdrives' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowfullscanonmappednetworkdrives_1' ; settingValueTemplateReference = @{settingValueTemplateId = '3e920b10-3773-4ac5-957e-e5573aec6d04' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'dac47505-f072-48d6-9f23-8d93262d58ed' } } } - } { $_.AllowFullScanRemovable } { - @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowfullscanremovabledrivescanning' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowfullscanremovabledrivescanning_1' ; settingValueTemplateReference = @{settingValueTemplateId = '366c5727-629b-4a81-b50b-52f90282fa2c' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'fb36e70b-5bc9-488a-a949-8ea3ac1634d5' } } } - } { $_.AllowIPS } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowintrusionpreventionsystem' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowintrusionpreventionsystem_1'; settingValueTemplateReference = @{settingValueTemplateId = '03738a99-7065-44cb-ba1e-93530ed906a7' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'd47f06e2-5378-43f2-adbc-e924538f1512' } } } - } { $_.AllowDownloadable } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowioavprotection' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowioavprotection_1'; settingValueTemplateReference = @{settingValueTemplateId = 'df4e6cbd-f7ff-41c8-88cd-fa25264a237e' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'fa06231d-aed4-4601-b631-3a37e85b62a0' } } } - } { $_.AllowRealTime } { - @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowrealtimemonitoring'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowrealtimemonitoring_1'; settingValueTemplateReference = @{settingValueTemplateId = '0492c452-1069-4b91-9363-93b8e006ab12' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f0790e28-9231-4d37-8f44-84bb47ca1b3e' } } } - } { $_.AllowNetwork } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowscanningnetworkfiles' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowscanningnetworkfiles_1' ; settingValueTemplateReference = @{settingValueTemplateId = '7b8c858c-a17d-4623-9e20-f34b851670ce' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f8f28442-0a6b-4b52-b42c-d31d9687c1cf' } } } - } { $_.AllowScriptScan } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowscriptscanning'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowscriptscanning_1'; settingValueTemplateReference = @{settingValueTemplateId = 'ab9e4320-c953-4067-ac9a-be2becd06b4a' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = '000cf176-949c-4c08-a5d4-90ed43718db7' } } } - } { $_.AllowUI } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowuseruiaccess' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowuseruiaccess_1' ; settingValueTemplateReference = @{settingValueTemplateId = '4b6c9739-4449-4006-8e5f-3049136470ea' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '0170a900-b0bc-4ccc-b7ce-dda9be49189b' } } } - } { $_.CheckSig } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_checkforsignaturesbeforerunningscan' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_checkforsignaturesbeforerunningscan_1' ; settingValueTemplateReference = @{settingValueTemplateId = '010779d1-edd4-441d-8034-89ad57a863fe' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = '4fea56e3-7bb6-4ad3-88c6-e364dd2f97b9' } } } - } { $_.DisableCatchupFullScan } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_disablecatchupfullscan'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_disablecatchupfullscan_1' ; settingValueTemplateReference = @{settingValueTemplateId = '1b26092f-48c4-447b-99d4-e9c501542f1c' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f881b08c-f047-40d2-b7d9-3dde7ce9ef64' } } } - } { $_.DisableCatchupQuickScan } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_disablecatchupquickscan' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_disablecatchupquickscan_1' ; settingValueTemplateReference = @{settingValueTemplateId = 'd263ced7-0d23-4095-9326-99c8b3f5d35b' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'dabf6781-9d5d-42da-822a-d4327aa2bdd1' } } } - } { $_.NetworkProtectionBlock } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_enablenetworkprotection' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_enablenetworkprotection_1' ; settingValueTemplateReference = @{settingValueTemplateId = 'ee58fb51-9ae5-408b-9406-b92b643f388a' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f53ab20e-8af6-48f5-9fa1-46863e1e517e' } } } - } { $_.LowCPU } { - @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_enablelowcpupriority' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_enablelowcpupriority_1' ; settingValueTemplateReference = @{settingValueTemplateId = '045a4a13-deee-4e24-9fe4-985c9357680d' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'cdeb96cf-18f5-4477-a710-0ea9ecc618af' } } } + $Tenants = ($Request.body.selectedTenants).defaultDomainName + if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } + $Compliance = $request.body.Compliance + $PolicySettings = $request.body.Policy + $ASR = $request.body.ASR + $EDR = $request.body.EDR + $results = foreach ($Tenant in $tenants) { + try { + $SettingsObj = @{ + id = 'fc780465-2017-40d4-a0c5-307022471b92' + androidEnabled = [bool]$Compliance.ConnectAndroid + iosEnabled = [bool]$Compliance.ConnectIos + windowsEnabled = [bool]$Compliance.Connectwindows + macEnabled = [bool]$Compliance.ConnectMac + partnerUnsupportedOsVersionBlocked = [bool]$Compliance.BlockunsupportedOS + partnerUnresponsivenessThresholdInDays = 7 + allowPartnerToCollectIOSApplicationMetadata = [bool]$Compliance.ConnectIosCompliance + allowPartnerToCollectIOSPersonalApplicationMetadata = [bool]$Compliance.ConnectIosCompliance + androidMobileApplicationManagementEnabled = [bool]$Compliance.ConnectAndroidCompliance + iosMobileApplicationManagementEnabled = [bool]$Compliance.appSync + microsoftDefenderForEndpointAttachEnabled = [bool]$compliance.AllowMEMEnforceCompliance + } | ConvertTo-Json -Compress + $SettingsRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/' -tenantid $tenant -type POST -body $SettingsObj + "$($Tenant): Successfully set Defender Compliance and Reporting settings" + + $Settings = switch ($PolicySettings) { + { $_.ScanArchives } { + @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowarchivescanning'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowarchivescanning_1'; settingValueTemplateReference = @{settingValueTemplateId = '9ead75d4-6f30-4bc5-8cc5-ab0f999d79f0' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '7c5c9cde-f74d-4d11-904f-de4c27f72d89' } } } + } { $_.AllowBehavior } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowbehaviormonitoring' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowbehaviormonitoring_1'; settingValueTemplateReference = @{settingValueTemplateId = '905921da-95e2-4a10-9e30-fe5540002ce1' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '8eef615a-1aa0-46f4-a25a-12cbe65de5ab' } } } + } { $_.AllowCloudProtection } { + @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowcloudprotection'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowcloudprotection_1'; settingValueTemplateReference = @{settingValueTemplateId = '16fe8afd-67be-4c50-8619-d535451a500c' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '7da139f1-9b7e-407d-853a-c2e5037cdc70' } } } + } { $_.AllowEmailScanning } { + @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowemailscanning' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowemailscanning_1'; settingValueTemplateReference = @{settingValueTemplateId = 'fdf107fd-e13b-4507-9d8f-db4d93476af9' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'b0d9ee81-de6a-4750-86d7-9397961c9852' } } } + } { $_.AllowFullScanNetwork } { + @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowfullscanonmappednetworkdrives' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowfullscanonmappednetworkdrives_1' ; settingValueTemplateReference = @{settingValueTemplateId = '3e920b10-3773-4ac5-957e-e5573aec6d04' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'dac47505-f072-48d6-9f23-8d93262d58ed' } } } + } { $_.AllowFullScanRemovable } { + @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowfullscanremovabledrivescanning' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowfullscanremovabledrivescanning_1' ; settingValueTemplateReference = @{settingValueTemplateId = '366c5727-629b-4a81-b50b-52f90282fa2c' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'fb36e70b-5bc9-488a-a949-8ea3ac1634d5' } } } + } { $_.AllowIPS } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowintrusionpreventionsystem' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowintrusionpreventionsystem_1'; settingValueTemplateReference = @{settingValueTemplateId = '03738a99-7065-44cb-ba1e-93530ed906a7' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'd47f06e2-5378-43f2-adbc-e924538f1512' } } } + } { $_.AllowDownloadable } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowioavprotection' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowioavprotection_1'; settingValueTemplateReference = @{settingValueTemplateId = 'df4e6cbd-f7ff-41c8-88cd-fa25264a237e' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'fa06231d-aed4-4601-b631-3a37e85b62a0' } } } + } { $_.AllowRealTime } { + @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowrealtimemonitoring'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowrealtimemonitoring_1'; settingValueTemplateReference = @{settingValueTemplateId = '0492c452-1069-4b91-9363-93b8e006ab12' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f0790e28-9231-4d37-8f44-84bb47ca1b3e' } } } + } { $_.AllowNetwork } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowscanningnetworkfiles' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowscanningnetworkfiles_1' ; settingValueTemplateReference = @{settingValueTemplateId = '7b8c858c-a17d-4623-9e20-f34b851670ce' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f8f28442-0a6b-4b52-b42c-d31d9687c1cf' } } } + } { $_.AllowScriptScan } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowscriptscanning'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowscriptscanning_1'; settingValueTemplateReference = @{settingValueTemplateId = 'ab9e4320-c953-4067-ac9a-be2becd06b4a' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = '000cf176-949c-4c08-a5d4-90ed43718db7' } } } + } { $_.AllowUI } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowuseruiaccess' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_allowuseruiaccess_1' ; settingValueTemplateReference = @{settingValueTemplateId = '4b6c9739-4449-4006-8e5f-3049136470ea' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '0170a900-b0bc-4ccc-b7ce-dda9be49189b' } } } + } { $_.CheckSig } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_checkforsignaturesbeforerunningscan' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_checkforsignaturesbeforerunningscan_1' ; settingValueTemplateReference = @{settingValueTemplateId = '010779d1-edd4-441d-8034-89ad57a863fe' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = '4fea56e3-7bb6-4ad3-88c6-e364dd2f97b9' } } } + } { $_.DisableCatchupFullScan } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_disablecatchupfullscan'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_disablecatchupfullscan_1' ; settingValueTemplateReference = @{settingValueTemplateId = '1b26092f-48c4-447b-99d4-e9c501542f1c' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f881b08c-f047-40d2-b7d9-3dde7ce9ef64' } } } + } { $_.DisableCatchupQuickScan } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_disablecatchupquickscan' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_disablecatchupquickscan_1' ; settingValueTemplateReference = @{settingValueTemplateId = 'd263ced7-0d23-4095-9326-99c8b3f5d35b' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'dabf6781-9d5d-42da-822a-d4327aa2bdd1' } } } + } { $_.NetworkProtectionBlock } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_enablenetworkprotection' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_enablenetworkprotection_1' ; settingValueTemplateReference = @{settingValueTemplateId = 'ee58fb51-9ae5-408b-9406-b92b643f388a' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'f53ab20e-8af6-48f5-9fa1-46863e1e517e' } } } + } { $_.LowCPU } { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_enablelowcpupriority' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_enablelowcpupriority_1' ; settingValueTemplateReference = @{settingValueTemplateId = '045a4a13-deee-4e24-9fe4-985c9357680d' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'cdeb96cf-18f5-4477-a710-0ea9ecc618af' } } } + } } - } - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" -tenantid $tenant - Write-Host ($CheckExististing | ConvertTo-Json) - if ('Default AV Policy' -in $CheckExististing.Name) { - "$($Tenant): AV Policy already exists. Skipping" - } - else { - $PolBody = ConvertTo-Json -Depth 10 -Compress -InputObject @{ - name = 'Default AV Policy' + $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant + Write-Host ($CheckExististing | ConvertTo-Json) + if ('Default AV Policy' -in $CheckExististing.Name) { + "$($Tenant): AV Policy already exists. Skipping" + } + else { + $PolBody = ConvertTo-Json -Depth 10 -Compress -InputObject @{ + name = 'Default AV Policy' + description = '' + platforms = 'windows10' + technologies = 'mdm,microsoftSense' + roleScopeTagIds = @('0') + templateReference = @{templateId = '804339ad-1553-4478-a742-138fb5807418_1' } + settings = $Settings + } + $PolicyRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $PolBody + if ($PolicySettings.AssignTo -ne 'None') { + $AssignBody = if ($PolicySettings.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($PolicySettings.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($PolicyRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $($PolicySettings.AssignTo)" -Sev 'Info' + } + "$($Tenant): Successfully set Default AV Policy settings" + } + $ASRSettings = switch ($ASR) { + { $_.BlockAdobeChild } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses_block' } } } + { $_.BlockWin32Macro } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses_block' } } } + { $_.BlockCredentialStealing } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockcredentialstealingfromwindowslocalsecurityauthoritysubsystem' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockcredentialstealingfromwindowslocalsecurityauthoritysubsystem_block' } } } + { $_.BlockPSExec } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockprocesscreationsfrompsexecandwmicommands'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockprocesscreationsfrompsexecandwmicommands_block' } } } + { $_.WMIPersistence } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockpersistencethroughwmieventsubscription' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockpersistencethroughwmieventsubscription_block' } } } + { $_.BlockOfficeExes } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfromcreatingexecutablecontent' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfromcreatingexecutablecontent_block' } } } + { $_.BlockOfficeApps } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfrominjectingcodeintootherprocesses' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfrominjectingcodeintootherprocesses_block' } } } + { $_.BlockYoungExe } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablefilesrunningunlesstheymeetprevalenceagetrustedlistcriterion' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablefilesrunningunlesstheymeetprevalenceagetrustedlistcriterion_block' } } } + { $_.blockJSVB } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockjavascriptorvbscriptfromlaunchingdownloadedexecutablecontent' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockjavascriptorvbscriptfromlaunchingdownloadedexecutablecontent_block' } } } + { $_.blockOfficeComChild } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficecommunicationappfromcreatingchildprocesses' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficecommunicationappfromcreatingchildprocesses_block' } } } + { $_.blockOfficeChild } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockallofficeapplicationsfromcreatingchildprocesses' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockallofficeapplicationsfromcreatingchildprocesses_block' } } } + { $_.BlockUntrustedUSB } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockuntrustedunsignedprocessesthatrunfromusb'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockuntrustedunsignedprocessesthatrunfromusb_block' } } } + { $_.EnableRansomwareVac } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware_block' } } } + { $_.BlockExesMail } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablecontentfromemailclientandwebmail' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablecontentfromemailclientandwebmail_block' } } } + { $_.BlockUnsignedDrivers } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockabuseofexploitedvulnerablesigneddrivers'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockabuseofexploitedvulnerablesigneddrivers_block' } } } + + } + + + $ASRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ + name = 'ASR Default rules' description = '' platforms = 'windows10' technologies = 'mdm,microsoftSense' roleScopeTagIds = @('0') - templateReference = @{templateId = '804339ad-1553-4478-a742-138fb5807418_1' } - settings = $Settings - } - $PolicyRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" -tenantid $tenant -type POST -body $PolBody - if ($PolicySettings.AssignTo -ne "None") { - $AssignBody = if ($PolicySettings.AssignTo -ne "AllDevicesAndUsers") { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($PolicySettings.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($PolicyRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $($PolicySettings.AssignTo)" -Sev "Info" + templateReference = @{templateId = 'e8c053d6-9f95-42b1-a7f1-ebfd71c67a4b_1' } + settings = @(@{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' + settingInstance = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules' + groupSettingCollectionValue = @(@{children = $asrSettings }) + settingInstanceTemplateReference = @{settingInstanceTemplateId = '19600663-e264-4c02-8f55-f2983216d6d7' } + } + }) } - "$($Tenant): Successfully set Default AV Policy settings" - } - $ASRSettings = switch ($ASR) { - { $_.BlockAdobeChild } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses_block' } } } - { $_.BlockWin32Macro } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockadobereaderfromcreatingchildprocesses_block' } } } - { $_.BlockCredentialStealing } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockcredentialstealingfromwindowslocalsecurityauthoritysubsystem' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockcredentialstealingfromwindowslocalsecurityauthoritysubsystem_block' } } } - { $_.BlockPSExec } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockprocesscreationsfrompsexecandwmicommands'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockprocesscreationsfrompsexecandwmicommands_block' } } } - { $_.WMIPersistence } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockpersistencethroughwmieventsubscription' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockpersistencethroughwmieventsubscription_block' } } } - { $_.BlockOfficeExes } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfromcreatingexecutablecontent' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfromcreatingexecutablecontent_block' } } } - { $_.BlockOfficeApps } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfrominjectingcodeintootherprocesses' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficeapplicationsfrominjectingcodeintootherprocesses_block' } } } - { $_.BlockYoungExe } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablefilesrunningunlesstheymeetprevalenceagetrustedlistcriterion' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablefilesrunningunlesstheymeetprevalenceagetrustedlistcriterion_block' } } } - { $_.blockJSVB } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockjavascriptorvbscriptfromlaunchingdownloadedexecutablecontent' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockjavascriptorvbscriptfromlaunchingdownloadedexecutablecontent_block' } } } - { $_.blockOfficeComChild } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficecommunicationappfromcreatingchildprocesses' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockofficecommunicationappfromcreatingchildprocesses_block' } } } - { $_.blockOfficeChild } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockallofficeapplicationsfromcreatingchildprocesses' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockallofficeapplicationsfromcreatingchildprocesses_block' } } } - { $_.BlockUntrustedUSB } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockuntrustedunsignedprocessesthatrunfromusb'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockuntrustedunsignedprocessesthatrunfromusb_block' } } } - { $_.EnableRansomwareVac } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware'; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware_block' } } } - { $_.BlockExesMail } { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablecontentfromemailclientandwebmail' ; choiceSettingValue = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue' ; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockexecutablecontentfromemailclientandwebmail_block' } } } - { $_.BlockUnsignedDrivers } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockabuseofexploitedvulnerablesigneddrivers'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockabuseofexploitedvulnerablesigneddrivers_block' } } } - - } - - - $ASRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ - name = 'ASR Default rules' - description = '' - platforms = 'windows10' - technologies = 'mdm,microsoftSense' - roleScopeTagIds = @('0') - templateReference = @{templateId = 'e8c053d6-9f95-42b1-a7f1-ebfd71c67a4b_1' } - settings = @(@{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' - settingInstance = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules' - groupSettingCollectionValue = @(@{children = $asrSettings }) - settingInstanceTemplateReference = @{settingInstanceTemplateId = '19600663-e264-4c02-8f55-f2983216d6d7' } - } - }) - } - $CheckExististingASR = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" -tenantid $tenant - if ('ASR Default rules' -in $CheckExististingASR.Name) { - "$($Tenant): ASR Policy already exists. Skipping" - } - else { - Write-Host $ASRbody - $ASRRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" -tenantid $tenant -type POST -body $ASRbody - Write-Host ($ASRRequest.id) - if ($ASR.AssignTo -ne "none") { - $AssignBody = if ($ASR.AssignTo -ne "AllDevicesAndUsers") { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($ASRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $($ASR.AssignTo)" -Sev "Info" + $CheckExististingASR = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant + if ('ASR Default rules' -in $CheckExististingASR.Name) { + "$($Tenant): ASR Policy already exists. Skipping" } - "$($Tenant): Successfully added ASR Settings" - } - - $EDRSettings = switch ($EDR) { - { $_.SampleSharing } { - @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' - settingInstance = @{ - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - settingDefinitionId = "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing" - choiceSettingValue = @{ - settingValueTemplateReference = @{settingValueTemplateId = "f72c326c-7c5b-4224-b890-0b9b54522bd9" } - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue" - 'value' = "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing_1" - } - settingInstanceTemplateReference = @{settingInstanceTemplateId = "6998c81e-2814-4f5e-b492-a6159128a97b" } - } - } + else { + Write-Host $ASRbody + $ASRRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $ASRbody + Write-Host ($ASRRequest.id) + if ($ASR.AssignTo -ne 'none') { + $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($ASRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $($ASR.AssignTo)" -Sev 'Info' + } + "$($Tenant): Successfully added ASR Settings" } - { $_.Telemetry } { - @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' - settingInstance = @{ - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - settingDefinitionId = "device_vendor_msft_windowsadvancedthreatprotection_configuration_telemetryreportingfrequency" - choiceSettingValue = @{ - settingValueTemplateReference = @{settingValueTemplateId = "350b0bea-b67b-43d4-9a04-c796edb961fd" } - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue" - 'value' = "device_vendor_msft_windowsadvancedthreatprotection_configuration_telemetryreportingfrequency_2" + + $EDRSettings = switch ($EDR) { + { $_.SampleSharing } { + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' + settingInstance = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing' + choiceSettingValue = @{ + settingValueTemplateReference = @{settingValueTemplateId = 'f72c326c-7c5b-4224-b890-0b9b54522bd9' } + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' + 'value' = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing_1' + } + settingInstanceTemplateReference = @{settingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' } } - settingInstanceTemplateReference = @{settingInstanceTemplateId = "03de6095-07c4-4f35-be38-c1cd3bae4484" } - } - } - - } - { $_.Config } { - @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' - settingInstance = @{ - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - settingDefinitionId = "device_vendor_msft_windowsadvancedthreatprotection_configurationtype" - choiceSettingValue = @{ - '@odata.type' = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue" - 'value' = "device_vendor_msft_windowsadvancedthreatprotection_configurationtype_autofromconnector" - settingValueTemplateReference = @{settingValueTemplateId = "e5c7c98c-c854-4140-836e-bd22db59d651" } - children = @(@{'@odata.type' = "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" ; settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_onboarding_fromconnector' ; simpleSettingValue = @{'@odata.type' = "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" ; value = "Microsoft ATP connector enabled"; valueState = "NotEncrypted" } } ) + } + } + { $_.Telemetry } { + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' + settingInstance = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_telemetryreportingfrequency' + choiceSettingValue = @{ + settingValueTemplateReference = @{settingValueTemplateId = '350b0bea-b67b-43d4-9a04-c796edb961fd' } + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' + 'value' = 'device_vendor_msft_windowsadvancedthreatprotection_configuration_telemetryreportingfrequency_2' + } + settingInstanceTemplateReference = @{settingInstanceTemplateId = '03de6095-07c4-4f35-be38-c1cd3bae4484' } } + } + + } + { $_.Config } { + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' + settingInstance = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_configurationtype' + choiceSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue' + 'value' = 'device_vendor_msft_windowsadvancedthreatprotection_configurationtype_autofromconnector' + settingValueTemplateReference = @{settingValueTemplateId = 'e5c7c98c-c854-4140-836e-bd22db59d651' } + children = @(@{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' ; settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_onboarding_fromconnector' ; simpleSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSecretSettingValue' ; value = 'Microsoft ATP connector enabled'; valueState = 'NotEncrypted' } } ) + } - settingInstanceTemplateReference = @{settingInstanceTemplateId = "23ab0ea3-1b12-429a-8ed0-7390cf699160" } - } - } + settingInstanceTemplateReference = @{settingInstanceTemplateId = '23ab0ea3-1b12-429a-8ed0-7390cf699160' } + } + } + } } - } - $EDRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ - name = 'EDR Configuration' - description = '' - platforms = 'windows10' - technologies = 'mdm,microsoftSense' - roleScopeTagIds = @('0') - templateReference = @{templateId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' } - settings = @($EDRSettings) - } - Write-Host ( $EDRbody) - $CheckExististingEDR = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" -tenantid $tenant - if ('EDR Configuration' -in $CheckExististingEDR.Name) { - "$($Tenant): EDR Policy already exists. Skipping" - } - else { - $EDRRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" -tenantid $tenant -type POST -body $EDRbody - if ($ASR.AssignTo -ne "none") { - $AssignBody = if ($ASR.AssignTo -ne "AllDevicesAndUsers") { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($EDRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned EDR policy $($Displayname) to $($ASR.AssignTo)" -Sev "Info" + $EDRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ + name = 'EDR Configuration' + description = '' + platforms = 'windows10' + technologies = 'mdm,microsoftSense' + roleScopeTagIds = @('0') + templateReference = @{templateId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' } + settings = @($EDRSettings) + } + Write-Host ( $EDRbody) + $CheckExististingEDR = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant + if ('EDR Configuration' -in $CheckExististingEDR.Name) { + "$($Tenant): EDR Policy already exists. Skipping" + } + else { + $EDRRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $EDRbody + if ($ASR.AssignTo -ne 'none') { + $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($EDRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned EDR policy $($Displayname) to $($ASR.AssignTo)" -Sev 'Info' + } + "$($Tenant): Successfully added EDR Settings" } - "$($Tenant): Successfully added EDR Settings" + + } + catch { + "Failed to add policy for $($Tenant): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed adding policy $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + continue } } - catch { - "Failed to add policy for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed adding policy $($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue - } - -} -$body = [pscustomobject]@{"Results" = @($results) } + $body = [pscustomobject]@{'Results' = @($results) } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddEnrollment.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddEnrollment.ps1 index 512c7ac30956..f74ce07857d1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddEnrollment.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddEnrollment.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddEnrollment { +Function Invoke-AddEnrollment { <# .FUNCTIONALITY Entrypoint @@ -8,57 +8,26 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' -# Input bindings are passed in via param block. -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -$Profbod = $Request.body -$results = foreach ($Tenant in $tenants) { - try { - $ObjBody = [pscustomobject]@{ - "@odata.type" = "#microsoft.graph.windows10EnrollmentCompletionPageConfiguration" - "id" = "DefaultWindows10EnrollmentCompletionPageConfiguration" - "displayName" = "All users and all devices" - "description" = "This is the default enrollment status screen configuration applied with the lowest priority to all users and all devices regardless of group membership." - "showInstallationProgress" = [bool]$Profbod.ShowProgress - "blockDeviceSetupRetryByUser" = [bool]$Profbod.blockDevice - "allowDeviceResetOnInstallFailure" = [bool]$Profbod.AllowReset - "allowLogCollectionOnInstallFailure" = [bool]$Profbod.EnableLog - "customErrorMessage" = $Profbod.ErrorMessage - "installProgressTimeoutInMinutes" = $Profbod.TimeOutInMinutes - "allowDeviceUseOnInstallFailure" = [bool]$Profbod.AllowFail - "selectedMobileAppIds" = @() - "trackInstallProgressForAutopilotOnly" = [bool]$Profbod.OBEEOnly - "disableUserStatusTrackingAfterFirstUser" = $true - "roleScopeTagIds" = @() - } - $Body = ConvertTo-Json -InputObject $ObjBody - Write-Host $body - $ExistingStatusPage = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations" -tenantid $Tenant) | Where-Object { $_.id -like "*DefaultWindows10EnrollmentCompletionPageConfiguration" } - $GraphRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations/$($ExistingStatusPage.ID)" -body $body -Type PATCH -tenantid $tenant - "Successfully changed default enrollment status page for $($Tenant)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Added Autopilot Enrollment Status Page $($Displayname)" -Sev "Info" - - } - catch { - "Failed to change default enrollment status page for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed adding Autopilot Enrollment Status Page $($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue + # Input bindings are passed in via param block. + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $Profbod = $Request.body + $results = foreach ($Tenant in $tenants) { + Set-CIPPDefaultAPEnrollment -TenantFilter $Tenant -ShowProgress $Profbod.ShowProgress -BlockDevice $Profbod.blockDevice -AllowReset $Profbod.AllowReset -EnableLog $Profbod.EnableLog -ErrorMessage $Profbod.ErrorMessage -TimeOutInMinutes $Profbod.TimeOutInMinutes -AllowFail $Profbod.AllowFail -OBEEOnly $Profbod.OBEEOnly } -} - -$body = [pscustomobject]@{"Results" = $results } + $body = [pscustomobject]@{'Results' = $results } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnector.ps1 index fb4e739bfed4..3686d66c124d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnector.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnector.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddExConnector { +Function Invoke-AddExConnector { <# .FUNCTIONALITY Entrypoint @@ -8,28 +8,30 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -$ConnectorType = ($Request.body.PowerShellCommand | ConvertFrom-Json).cippConnectorType -$RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, cippConnectorType, comments + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -$Result = foreach ($Tenantfilter in $tenants) { - try { - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams - "Successfully created transport rule for $tenantfilter." - Write-LogMessage -API $APINAME -tenant $tenantfilter -message "Created transport rule for $($tenantfilter)" -sev Debug - } - catch { - "Could not create created transport rule for $($tenantfilter): $($_.Exception.message)" + $ConnectorType = ($Request.body.PowerShellCommand | ConvertFrom-Json).cippConnectorType + $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, cippConnectorType, comments + + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $Result = foreach ($Tenantfilter in $tenants) { + try { + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams + "Successfully created transport rule for $Tenantfilter." + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Tenantfilter -message "Created transport rule for $($Tenantfilter)" -sev 'Info' + } + catch { + "Could not create created transport rule for $($Tenantfilter): $($_.Exception.message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Tenantfilter -message "Could not create created transport rule for $($Tenantfilter): $($_.Exception.message)" -sev 'Error' + } } -} - -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{Results = @($Result) } - }) - } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{Results = @($Result) } + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnectorTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnectorTemplate.ps1 index 099d51c2a7c0..73cf56b8d910 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnectorTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddExConnectorTemplate.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddExConnectorTemplate { +Function Invoke-AddExConnectorTemplate { <# .FUNCTIONALITY Entrypoint @@ -8,49 +8,50 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -Write-Host ($request | ConvertTo-Json -Compress) + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -try { - $GUID = (New-Guid).GUID - $Select = if ($Request.body.cippconnectortype -eq "outbound") { - @( - "name", "AllAcceptedDomains", "CloudServicesMailEnabled", "Comment", "Confirm", "ConnectorSource", "ConnectorType", "Enabled", "IsTransportRuleScoped", "RecipientDomains", "RouteAllMessagesViaOnPremises", "SenderRewritingEnabled", "SmartHosts", "TestMode", "TlsDomain", "TlsSettings", "UseMXRecord" - ) - } - else { - @( - "name", "SenderDomains", "ConnectorSource", "ConnectorType", "EFSkipIPs", "EFSkipLastIP", "EFSkipMailGateway", "EFTestMode", "EFUsers", "Enabled ", "RequireTls", "RestrictDomainsToCertificate", "RestrictDomainsToIPAddresses", "ScanAndDropRecipients", "SenderIPAddresses", "TlsSenderCertificateName", "TreatMessagesAsInternal", "TrustedOrganizations" - ) - } + Write-Host ($request | ConvertTo-Json -Compress) - $JSON = ([pscustomobject]$Request.body | Select-Object $Select) | ForEach-Object { - $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name - $_ | Select-Object -Property $NonEmptyProperties + try { + $GUID = (New-Guid).GUID + $Select = if ($Request.body.cippconnectortype -eq 'outbound') { + @( + 'name', 'AllAcceptedDomains', 'CloudServicesMailEnabled', 'Comment', 'Confirm', 'ConnectorSource', 'ConnectorType', 'Enabled', 'IsTransportRuleScoped', 'RecipientDomains', 'RouteAllMessagesViaOnPremises', 'SenderRewritingEnabled', 'SmartHosts', 'TestMode', 'TlsDomain', 'TlsSettings', 'UseMXRecord' + ) + } + else { + @( + 'name', 'SenderDomains', 'ConnectorSource', 'ConnectorType', 'EFSkipIPs', 'EFSkipLastIP', 'EFSkipMailGateway', 'EFTestMode', 'EFUsers', 'Enabled ', 'RequireTls', 'RestrictDomainsToCertificate', 'RestrictDomainsToIPAddresses', 'ScanAndDropRecipients', 'SenderIPAddresses', 'TlsSenderCertificateName', 'TreatMessagesAsInternal', 'TrustedOrganizations' + ) + } + + $JSON = ([pscustomobject]$Request.body | Select-Object $Select) | ForEach-Object { + $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name + $_ | Select-Object -Property $NonEmptyProperties + } + $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, * | ConvertTo-Json -Depth 10) + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$json" + RowKey = "$GUID" + direction = $request.body.cippconnectortype + PartitionKey = 'ExConnectorTemplate' + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Connector Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' + $body = [pscustomobject]@{'Results' = 'Successfully added template' } } - $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, * | ConvertTo-Json -Depth 10) - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$json" - RowKey = "$GUID" - direction = $request.body.cippconnectortype - PartitionKey = "ExConnectorTemplate" + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Connector Template: $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Connector Template creation failed: $($_.Exception.Message)" } } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Connector Template $($Request.body.name) with GUID $GUID" -Sev "Debug" - $body = [pscustomobject]@{"Results" = "Successfully added template" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Connector Template: $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Connector Template creation failed: $($_.Exception.Message)" } -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroup.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroup.ps1 index b52d4091b595..9794b0d51f3c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroup.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddGroup { +Function Invoke-AddGroup { <# .FUNCTIONALITY Entrypoint @@ -8,68 +8,68 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$groupobj = $Request.body -$SelectedTenants = if ($Request.body.selectedTenants) { $request.body.selectedTenants.defaultDomainName } else { $Request.body.tenantid } -if ("AllTenants" -in $SelectedTenants) { $SelectedTenants = (Get-Tenants).defaultDomainName } + $groupobj = $Request.body + $SelectedTenants = if ($Request.body.selectedTenants) { $request.body.selectedTenants.defaultDomainName } else { $Request.body.tenantid } + if ('AllTenants' -in $SelectedTenants) { $SelectedTenants = (Get-Tenants).defaultDomainName } -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." -$results = foreach ($tenant in $SelectedTenants) { - try { - $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($tenant)" } - if ($groupobj.groupType -in "Generic", "azurerole", "dynamic") { - - $BodyToship = [pscustomobject] @{ - "displayName" = $groupobj.Displayname - "description" = $groupobj.Description - "mailNickname" = $groupobj.username - mailEnabled = [bool]$false - securityEnabled = [bool]$true - isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ "AzureRole") - } - if ($groupobj.membershipRules) { - $BodyToship | Add-Member -NotePropertyName "membershipRule" -NotePropertyValue ($groupobj.membershipRules) - $BodyToship | Add-Member -NotePropertyName "groupTypes" -NotePropertyValue @("DynamicMembership") - $BodyToship | Add-Member -NotePropertyName "membershipRuleProcessingState" -NotePropertyValue "On" - } - if ($groupobj.AddOwner -AND $groupobj.groupType -in "generic", "azurerole", "security") { - $BodyToship | Add-Member -NotePropertyName "owners@odata.bind" -NotePropertyValue (($groupobj.AddOwner) | ForEach-Object { "https://graph.microsoft.com/v1.0/users/$($_.value)" }) - } - if ($groupobj.AddMember -AND $groupobj.groupType -in "generic", "azurerole", "security") { - $BodyToship | Add-Member -NotePropertyName "members@odata.bind" -NotePropertyValue (($groupobj.AddMember) | ForEach-Object { "https://graph.microsoft.com/v1.0/users/$($_.value)" }) - } - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups" -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose - } - else { - $Params = @{ - Name = $groupobj.Displayname - Alias = $groupobj.username - Description = $groupobj.Description - PrimarySmtpAddress = $email - Type = $groupobj.groupType - RequireSenderAuthenticationEnabled = [bool]!$groupobj.AllowExternal + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + $results = foreach ($tenant in $SelectedTenants) { + try { + $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($tenant)" } + if ($groupobj.groupType -in 'Generic', 'azurerole', 'dynamic') { + + $BodyToship = [pscustomobject] @{ + 'displayName' = $groupobj.Displayname + 'description' = $groupobj.Description + 'mailNickname' = $groupobj.username + mailEnabled = [bool]$false + securityEnabled = [bool]$true + isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ 'AzureRole') + } + if ($groupobj.membershipRules) { + $BodyToship | Add-Member -NotePropertyName 'membershipRule' -NotePropertyValue ($groupobj.membershipRules) + $BodyToship | Add-Member -NotePropertyName 'groupTypes' -NotePropertyValue @('DynamicMembership') + $BodyToship | Add-Member -NotePropertyName 'membershipRuleProcessingState' -NotePropertyValue 'On' + } + if ($groupobj.AddOwner -AND $groupobj.groupType -in 'generic', 'azurerole', 'security') { + $BodyToship | Add-Member -NotePropertyName 'owners@odata.bind' -NotePropertyValue (($groupobj.AddOwner) | ForEach-Object { "https://graph.microsoft.com/v1.0/users/$($_.value)" }) + $bodytoship.'owners@odata.bind' = @($bodytoship.'owners@odata.bind') + } + if ($groupobj.AddMember -AND $groupobj.groupType -in 'generic', 'azurerole', 'security') { + $BodyToship | Add-Member -NotePropertyName 'members@odata.bind' -NotePropertyValue (($groupobj.AddMember) | ForEach-Object { "https://graph.microsoft.com/v1.0/users/$($_.value)" }) + $BodyToship.'members@odata.bind' = @($BodyToship.'members@odata.bind') + } + $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose + } else { + $Params = @{ + Name = $groupobj.Displayname + Alias = $groupobj.username + Description = $groupobj.Description + PrimarySmtpAddress = $email + Type = $groupobj.groupType + RequireSenderAuthenticationEnabled = [bool]!$groupobj.AllowExternal + } + $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet 'New-DistributionGroup' -cmdParams $params + # At some point add logic to use AddOwner/AddMember for New-DistributionGroup, but idk how we're going to brr that - rvdwegen } - $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet "New-DistributionGroup" -cmdParams $params - # At some point add logic to use AddOwner/AddMember for New-DistributionGroup, but idk how we're going to brr that - rvdwegen - } - "Successfully created group $($groupobj.displayname) for $($tenant)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) " -Sev "Info" + "Successfully created group $($groupobj.displayname) for $($tenant)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id)" -Sev 'Info' + } catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Group creation API failed. $($_.Exception.Message)" -Sev 'Error' + "Failed to create group. $($groupobj.displayname) for $($tenant) $($_.Exception.Message)" + } } - catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Group creation API failed. $($_.Exception.Message)" -Sev "Error" - "Failed to create group. $($groupobj.displayname) for $($tenant) $($_.Exception.Message)" - } -} -$body = [pscustomobject]@{"Results" = @($results) } + $body = [pscustomobject]@{'Results' = @($results) } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroupTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroupTemplate.ps1 index 19ec092ca49b..85d10812a9c8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGroupTemplate.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddGroupTemplate { +Function Invoke-AddGroupTemplate { <# .FUNCTIONALITY Entrypoint @@ -8,43 +8,43 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" - -$GUID = (New-Guid).GUID -try { - if (!$Request.body.displayname) { throw "You must enter a displayname" } - - $object = [PSCustomObject]@{ - Displayname = $request.body.displayname - Description = $request.body.description - groupType = $request.body.groupType - MembershipRules = $request.body.membershipRule - allowExternal = $request.body.allowExternal - username = $request.body.username - GUID = $GUID - } | ConvertTo-Json - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$object" - RowKey = "$GUID" - PartitionKey = "GroupTemplate" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + $GUID = (New-Guid).GUID + try { + if (!$Request.body.displayname) { throw 'You must enter a displayname' } + + $object = [PSCustomObject]@{ + Displayname = $request.body.displayname + Description = $request.body.description + groupType = $request.body.groupType + MembershipRules = $request.body.membershipRule + allowExternal = $request.body.allowExternal + username = $request.body.username + GUID = $GUID + } | ConvertTo-Json + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$object" + RowKey = "$GUID" + PartitionKey = 'GroupTemplate' + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Group template named $($Request.body.displayname) with GUID $GUID" -Sev 'Debug' + + $body = [pscustomobject]@{'Results' = 'Successfully added template' } + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Group Template Creation failed: $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Group Template Creation failed: $($_.Exception.Message)" } } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Group template named $($Request.body.displayname) with GUID $GUID" -Sev "Info" - - $body = [pscustomobject]@{"Results" = "Successfully added template" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Group Template Creation failed: $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Group Template Creation failed: $($_.Exception.Message)" } -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGuest.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGuest.ps1 index 4c94ec4740f9..462ba7df0545 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGuest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddGuest.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddGuest { +Function Invoke-AddGuest { <# .FUNCTIONALITY Entrypoint @@ -8,49 +8,51 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -$Results = [System.Collections.ArrayList]@() -$userobj = $Request.body -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." -try { -if ($userobj.RedirectURL) { - $BodyToship = [pscustomobject] @{ - "InvitedUserDisplayName" = $userobj.Displayname - "InvitedUserEmailAddress" = $($userobj.mail) - "inviteRedirectUrl" = $($userobj.RedirectURL) - "sendInvitationMessage" = [boolean]$userobj.SendInvite - } -} -else {$BodyToship = [pscustomobject] @{ - "InvitedUserDisplayName" = $userobj.Displayname - "InvitedUserEmailAddress" = $($userobj.mail) - "sendInvitationMessage" = [boolean]$userobj.SendInvite - "inviteRedirectUrl" = "https://myapps.microsoft.com" -} -} - $bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/invitations" -tenantid $Userobj.tenantid -type POST -body $BodyToship -verbose - if ($Userobj.sendInvite -eq "true") { - $results.add("Invited Guest. Invite Email sent") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Invited Guest $($userobj.displayname) with Email Invite " -Sev "Info" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + $Results = [System.Collections.ArrayList]@() + $userobj = $Request.body + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + try { + if ($userobj.RedirectURL) { + $BodyToship = [pscustomobject] @{ + 'InvitedUserDisplayName' = $userobj.Displayname + 'InvitedUserEmailAddress' = $($userobj.mail) + 'inviteRedirectUrl' = $($userobj.RedirectURL) + 'sendInvitationMessage' = [boolean]$userobj.SendInvite + } + } + else { + $BodyToship = [pscustomobject] @{ + 'InvitedUserDisplayName' = $userobj.Displayname + 'InvitedUserEmailAddress' = $($userobj.mail) + 'sendInvitationMessage' = [boolean]$userobj.SendInvite + 'inviteRedirectUrl' = 'https://myapps.microsoft.com' + } + } + $bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress + $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/invitations' -tenantid $Userobj.tenantid -type POST -body $BodyToship -verbose + if ($Userobj.sendInvite -eq 'true') { + $results.add('Invited Guest. Invite Email sent') + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Invited Guest $($userobj.displayname) with Email Invite " -Sev 'Info' + } + else { + $results.add('Invited Guest. No Invite Email was sent') + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Invited Guest $($userobj.displayname) with no Email Invite " -Sev 'Info' + } } - else { - $results.add("Invited Guest. No Invite Email was sent") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Invited Guest $($userobj.displayname) with no Email Invite " -Sev "Info" + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Guest Invite API failed. $($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Failed to Invite Guest. $($_.Exception.Message)" ) } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Guest Invite API failed. $($_.Exception.Message)" -Sev "Error" - $body = $results.add("Failed to Invite Guest. $($_.Exception.Message)" ) -} -$body = @{"Results" = @($results) } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) + $body = @{'Results' = @($results) } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddIntuneTemplate.ps1 index 281c482d4d42..d8e651ae36ad 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddIntuneTemplate.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddIntuneTemplate { +Function Invoke-AddIntuneTemplate { <# .FUNCTIONALITY Entrypoint @@ -8,122 +8,121 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$GUID = (New-Guid).GUID -try { - if ($Request.body.rawJSON) { - if (!$Request.body.displayname) { throw "You must enter a displayname" } - if ($null -eq ($Request.body.Rawjson | ConvertFrom-Json)) { throw "the JSON is invalid" } + $GUID = (New-Guid).GUID + try { + if ($Request.body.rawJSON) { + if (!$Request.body.displayname) { throw 'You must enter a displayname' } + if ($null -eq ($Request.body.Rawjson | ConvertFrom-Json)) { throw 'the JSON is invalid' } - $object = [PSCustomObject]@{ - Displayname = $request.body.displayname - Description = $request.body.description - RAWJson = $request.body.RawJSON - Type = $request.body.TemplateType - GUID = $GUID - } | ConvertTo-Json - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$object" - RowKey = "$GUID" - PartitionKey = "IntuneTemplate" - } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created intune policy template named $($Request.body.displayname) with GUID $GUID" -Sev "Debug" + $object = [PSCustomObject]@{ + Displayname = $request.body.displayname + Description = $request.body.description + RAWJson = $request.body.RawJSON + Type = $request.body.TemplateType + GUID = $GUID + } | ConvertTo-Json + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$object" + RowKey = "$GUID" + PartitionKey = 'IntuneTemplate' + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created intune policy template named $($Request.body.displayname) with GUID $GUID" -Sev 'Debug' - $body = [pscustomobject]@{"Results" = "Successfully added template" } - } - else { - $TenantFilter = $request.query.TenantFilter - $URLName = $Request.query.URLName - $ID = $request.query.id - switch ($URLName) { + $body = [pscustomobject]@{'Results' = 'Successfully added template' } + } + else { + $TenantFilter = $request.query.TenantFilter + $URLName = $Request.query.URLName + $ID = $request.query.id + switch ($URLName) { - "configurationPolicies" { - $Type = "Catalog" - $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')?`$expand=settings" -tenantid $tenantfilter | Select-Object name, description, settings, platforms, technologies, templateReference - $TemplateJson = $Template | ConvertTo-Json -Depth 10 - $DisplayName = $template.name + 'configurationPolicies' { + $Type = 'Catalog' + $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')?`$expand=settings" -tenantid $tenantfilter | Select-Object name, description, settings, platforms, technologies, templateReference + $TemplateJson = $Template | ConvertTo-Json -Depth 10 + $DisplayName = $template.name - } - "deviceConfigurations" { - $Type = "Device" - $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)" -tenantid $tenantfilter | Select-Object * -ExcludeProperty id, lastModifiedDateTime, '@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime' - Write-Host ($Template | ConvertTo-Json) - $DisplayName = $template.displayName - $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 10 -Compress - } - "groupPolicyConfigurations" { - $Type = "Admin" - $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')" -tenantid $tenantfilter - $DisplayName = $Template.displayName - $TemplateJsonItems = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')/definitionValues?`$expand=definition" -tenantid $tenantfilter - $TemplateJsonSource = foreach ($TemplateJsonItem in $TemplateJsonItems) { - $presentationValues = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')/definitionValues('$($TemplateJsonItem.id)')/presentationValues?`$expand=presentation" -tenantid $tenantfilter | ForEach-Object { - $obj = $_ - if ($obj.id) { - $PresObj = @{ - id = $obj.id - "presentation@odata.bind" = "https://graph.microsoft.com/beta/deviceManagement/groupPolicyDefinitions('$($TemplateJsonItem.definition.id)')/presentations('$($obj.presentation.id)')" + } + 'deviceConfigurations' { + $Type = 'Device' + $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)" -tenantid $tenantfilter | Select-Object * -ExcludeProperty id, lastModifiedDateTime, '@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime' + Write-Host ($Template | ConvertTo-Json) + $DisplayName = $template.displayName + $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 10 -Compress + } + 'groupPolicyConfigurations' { + $Type = 'Admin' + $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')" -tenantid $tenantfilter + $DisplayName = $Template.displayName + $TemplateJsonItems = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')/definitionValues?`$expand=definition" -tenantid $tenantfilter + $TemplateJsonSource = foreach ($TemplateJsonItem in $TemplateJsonItems) { + $presentationValues = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')/definitionValues('$($TemplateJsonItem.id)')/presentationValues?`$expand=presentation" -tenantid $tenantfilter | ForEach-Object { + $obj = $_ + if ($obj.id) { + $PresObj = @{ + id = $obj.id + 'presentation@odata.bind' = "https://graph.microsoft.com/beta/deviceManagement/groupPolicyDefinitions('$($TemplateJsonItem.definition.id)')/presentations('$($obj.presentation.id)')" + } + if ($obj.values) { $PresObj['values'] = $obj.values } + if ($obj.value) { $PresObj['value'] = $obj.value } + if ($obj.'@odata.type') { $PresObj['@odata.type'] = $obj.'@odata.type' } + [pscustomobject]$PresObj } - if ($obj.values) { $PresObj['values'] = $obj.values } - if ($obj.value) { $PresObj['value'] = $obj.value } - if ($obj.'@odata.type') { $PresObj['@odata.type'] = $obj.'@odata.type' } - [pscustomobject]$PresObj + } + [PSCustomObject]@{ + 'definition@odata.bind' = "https://graph.microsoft.com/beta/deviceManagement/groupPolicyDefinitions('$($TemplateJsonItem.definition.id)')" + enabled = $TemplateJsonItem.enabled + presentationValues = @($presentationValues) } } - [PSCustomObject]@{ - 'definition@odata.bind' = "https://graph.microsoft.com/beta/deviceManagement/groupPolicyDefinitions('$($TemplateJsonItem.definition.id)')" - enabled = $TemplateJsonItem.enabled - presentationValues = @($presentationValues) + $inputvar = [pscustomobject]@{ + added = @($TemplateJsonSource) + updated = @() + deletedIds = @() + } - } - $inputvar = [pscustomobject]@{ - added = @($TemplateJsonSource) - updated = @() - deletedIds = @() + + $TemplateJson = (ConvertTo-Json -InputObject $inputvar -Depth 15 -Compress) } - + } - $TemplateJson = (ConvertTo-Json -InputObject $inputvar -Depth 15 -Compress) + $object = [PSCustomObject]@{ + Displayname = $DisplayName + Description = $Template.Description + RAWJson = $TemplateJson + Type = $Type + GUID = $GUID + } | ConvertTo-Json + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$object" + RowKey = "$GUID" + PartitionKey = 'IntuneTemplate' } - } - + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created intune policy template $($Request.body.displayname) with GUID $GUID using an original policy from a tenant" -Sev 'Debug' - $object = [PSCustomObject]@{ - Displayname = $DisplayName - Description = $Template.Description - RAWJson = $TemplateJson - Type = $Type - GUID = $GUID - } | ConvertTo-Json - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$object" - RowKey = "$GUID" - PartitionKey = "IntuneTemplate" + $body = [pscustomobject]@{'Results' = 'Successfully added template' } } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created intune policy template $($Request.body.displayname) with GUID $GUID using an original policy from a tenant" -Sev "Debug" - - $body = [pscustomobject]@{"Results" = "Successfully added template" } } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Intune Template Deployment failed: $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Intune Template Deployment failed: $($_.Exception.Message)" } -} + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Intune Template Deployment failed: $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Intune Template Deployment failed: $($_.Exception.Message)" } + } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddMSPApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddMSPApp.ps1 index 85c883333511..5bf0df7bf86d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddMSPApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddMSPApp.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddMSPApp { +Function Invoke-AddMSPApp { <# .FUNCTIONALITY Entrypoint @@ -8,90 +8,90 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -Write-Host 'PowerShell HTTP trigger function processed a request.' -$RMMApp = $request.body -$assignTo = $Request.body.AssignTo -$intuneBody = Get-Content "AddMSPApp\$($RMMApp.RMMName.value).app.json" | ConvertFrom-Json -$intuneBody.displayName = $RMMApp.DisplayName + Write-Host 'PowerShell HTTP trigger function processed a request.' + $RMMApp = $request.body + $assignTo = $Request.body.AssignTo + $intuneBody = Get-Content "AddMSPApp\$($RMMApp.RMMName.value).app.json" | ConvertFrom-Json + $intuneBody.displayName = $RMMApp.DisplayName -$Tenants = $request.body.selectedTenants -$Results = foreach ($Tenant in $tenants) { - $InstallParams = [pscustomobject]$RMMApp.params - switch ($rmmapp.RMMName.value) { - 'datto' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.DattoURL) -GUID $($InstallParams.DattoGUID["$($tenant.customerId)"])" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + $Tenants = $request.body.selectedTenants + $Results = foreach ($Tenant in $tenants) { + $InstallParams = [pscustomobject]$RMMApp.params + switch ($rmmapp.RMMName.value) { + 'datto' { + $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.DattoURL) -GUID $($InstallParams.DattoGUID["$($tenant.customerId)"])" + $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + } + 'ninja' { + $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" + $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + } + 'Huntress' { + $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -OrgKey $($InstallParams.Orgkey["$($tenant.customerId)"]) -acctkey $($InstallParams.AccountKey)" + $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\install.ps1 -Uninstall' + } + 'Immybot' { + $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -url $($InstallParams.ClientURL["$($tenant.customerId)"])" + $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + } + 'syncro' { + $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.ClientURL["$($tenant.customerId)"])" + $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + } + 'NCentral' { + $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" + $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + } + 'automate' { + $installcommandline = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\install.ps1 -Server $($InstallParams.Server) -InstallerToken $($InstallParams.InstallerToken["$($tenant.customerId)"]) -LocationID $($InstallParams.LocationID["$($tenant.customerId)"])" + $UninstallCommandLine = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\uninstall.ps1 -Server $($InstallParams.Server)" + $DetectionScript = (Get-Content 'AddMSPApp\automate.detection.ps1' -Raw) -replace '##SERVER##', $InstallParams.Server + $intuneBody.detectionRules[0].scriptContent = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($DetectionScript)) + } + 'cwcommand' { + $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -Url $($InstallParams.ClientURL["$($tenant.customerId)"])" + $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + } } - 'ninja' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' - } - 'Huntress' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -OrgKey $($InstallParams.Orgkey["$($tenant.customerId)"]) -acctkey $($InstallParams.AccountKey)" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\install.ps1 -Uninstall' - } - 'Immybot' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -url $($InstallParams.ClientURL["$($tenant.customerId)"])" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' - } - 'syncro' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.ClientURL["$($tenant.customerId)"])" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' - } - 'NCentral' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' - } - 'automate' { - $installcommandline = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\install.ps1 -Server $($InstallParams.Server) -InstallerToken $($InstallParams.InstallerToken["$($tenant.customerId)"]) -LocationID $($InstallParams.LocationID["$($tenant.customerId)"])" - $UninstallCommandLine = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\uninstall.ps1 -Server $($InstallParams.Server)" - $DetectionScript = (Get-Content 'AddMSPApp\automate.detection.ps1' -Raw) -replace '##SERVER##', $InstallParams.Server - $intuneBody.detectionRules[0].scriptContent = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($DetectionScript)) - } - 'cwcommand' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -Url $($InstallParams.ClientURL["$($tenant.customerId)"])" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' - } - } - $intuneBody.installCommandLine = $installcommandline - $intuneBody.UninstallCommandLine = $UninstallCommandLine + $intuneBody.installCommandLine = $installcommandline + $intuneBody.UninstallCommandLine = $UninstallCommandLine - try { - $CompleteObject = [PSCustomObject]@{ - tenant = $tenant.defaultDomainName - Applicationname = $RMMApp.DisplayName - assignTo = $assignTo - IntuneBody = $intunebody - type = 'MSPApp' - MSPAppName = $RMMApp.RMMName.value - } | ConvertTo-Json -Depth 15 - $Table = Get-CippTable -tablename 'apps' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$CompleteObject" - RowKey = "$((New-Guid).GUID)" - PartitionKey = "apps" - status = "Not Deployed yet" + try { + $CompleteObject = [PSCustomObject]@{ + tenant = $tenant.defaultDomainName + Applicationname = $RMMApp.DisplayName + assignTo = $assignTo + IntuneBody = $intunebody + type = 'MSPApp' + MSPAppName = $RMMApp.RMMName.value + } | ConvertTo-Json -Depth 15 + $Table = Get-CippTable -tablename 'apps' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$CompleteObject" + RowKey = "$((New-Guid).GUID)" + PartitionKey = 'apps' + status = 'Not Deployed yet' + } + "Successfully added MSP App for $($Tenant.defaultDomainName) to queue. " + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant.defaultDomainName -message "MSP Application $($intunebody.Displayname) queued to add" -Sev 'Info' + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant.defaultDomainName -message "Failed to add MSP Application $($intunebody.Displayname) to queue" -Sev 'Error' + "Failed to add MSP app for $($Tenant.defaultDomainName) to queue" } - "Successfully added MSP App for $($Tenant.defaultDomainName) to queue. " - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant.defaultDomainName -message "MSP Application $($intunebody.Displayname) queued to add" -Sev 'Info' - } - catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant.defaultDomainName -message "Failed to add MSP Application $($intunebody.Displayname) to queue" -Sev 'Error' - "Failed to add MSP app for $($Tenant.defaultDomainName) to queue" } -} -$body = [pscustomobject]@{'Results' = $results } + $body = [pscustomobject]@{'Results' = $results } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddNamedLocation.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddNamedLocation.ps1 index 48556531ca75..578b196ed014 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddNamedLocation.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddNamedLocation.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddNamedLocation { +Function Invoke-AddNamedLocation { <# .FUNCTIONALITY Entrypoint @@ -8,57 +8,57 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' -# Input bindings are passed in via param block. -$Tenants = $request.body.selectedTenants.defaultDomainName -Write-Host ($Request.body | ConvertTo-Json) -if ($Tenants -eq "AllTenants") { $Tenants = (Get-Tenants).defaultDomainName } -$results = foreach ($Tenant in $tenants) { - try { - $ObjBody = if ($Request.body.Type -eq "IPLocation") { - $IPRanges = ($Request.body.Ips -split "`n") | ForEach-Object { if ($_ -ne "") { @{cidrAddress = "$_" } } } - if (!$IPRanges) { $IPRanges = @(@{cidrAddress = "$($Request.Body.Ips)" }) } - [pscustomobject]@{ - "@odata.type" = "#microsoft.graph.ipNamedLocation" - displayName = $request.body.policyName - ipRanges = @($IPRanges) - isTrusted = $Request.body.Trusted + # Input bindings are passed in via param block. + $Tenants = $request.body.selectedTenants.defaultDomainName + Write-Host ($Request.body | ConvertTo-Json) + if ($Tenants -eq 'AllTenants') { $Tenants = (Get-Tenants).defaultDomainName } + $results = foreach ($Tenant in $tenants) { + try { + $ObjBody = if ($Request.body.Type -eq 'IPLocation') { + $IPRanges = ($Request.body.Ips -split "`n") | ForEach-Object { if ($_ -ne '') { @{cidrAddress = "$_" } } } + if (!$IPRanges) { $IPRanges = @(@{cidrAddress = "$($Request.Body.Ips)" }) } + [pscustomobject]@{ + '@odata.type' = '#microsoft.graph.ipNamedLocation' + displayName = $request.body.policyName + ipRanges = @($IPRanges) + isTrusted = $Request.body.Trusted + } } - } - else { - [pscustomobject]@{ - "@odata.type" = "#microsoft.graph.countryNamedLocation" - displayName = $request.body.policyName - countriesAndRegions = @($Request.Body.Countries.value) - includeUnknownCountriesAndRegions = $Request.body.includeUnknownCountriesAndRegions + else { + [pscustomobject]@{ + '@odata.type' = '#microsoft.graph.countryNamedLocation' + displayName = $request.body.policyName + countriesAndRegions = @($Request.Body.Countries.value) + includeUnknownCountriesAndRegions = $Request.body.includeUnknownCountriesAndRegions + } } + $Body = ConvertTo-Json -InputObject $ObjBody + $GraphRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -body $body -Type POST -tenantid $tenant + "Successfully added Named Location for $($Tenant)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Added Named Location $($Displayname)" -Sev 'Info' + + } + catch { + "Failed to add Named Location $($Tenant): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed adding Named Location$($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + continue } - $Body = ConvertTo-Json -InputObject $ObjBody - $GraphRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations" -body $body -Type POST -tenantid $tenant - "Successfully added Named Location for $($Tenant)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message " added Named Location $($Displayname)" -Sev "Info" } - catch { - "Failed to add Named Location $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed adding Named Location$($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue - } -} - -$body = [pscustomobject]@{"Results" = @($results) } + $body = [pscustomobject]@{'Results' = @($results) } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddOfficeApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddOfficeApp.ps1 index 732aa7dc231a..a5f9ec87c351 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddOfficeApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddOfficeApp.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddOfficeApp { +Function Invoke-AddOfficeApp { <# .FUNCTIONALITY Entrypoint @@ -8,95 +8,95 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' -# Input bindings are passed in via param block. -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -if ("AllTenants" -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } -$AssignTo = if ($request.body.Assignto -ne "on") { $request.body.Assignto } + # Input bindings are passed in via param block. + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } + $AssignTo = if ($request.body.Assignto -ne 'on') { $request.body.Assignto } -$results = foreach ($Tenant in $tenants) { - try { - $ExistingO365 = New-graphGetRequest -Uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps" -tenantid $tenant | Where-Object { $_.displayname -eq "Mifcrosoft 365 Apps for Windows 10 and later" } - if (!$ExistingO365) { - $Arch = if ($request.body.arch) { "x64" } else { "x86" } - $products = @("o365ProPlusRetail") - $ExcludedApps = [pscustomobject]@{ - infoPath = $true - sharePointDesigner = $true - excel = $false - lync = $false - oneNote = $false - outlook = $false - powerPoint = $false - publisher = $false - teams = $false - word = $false - access = $false - bing = $false + $results = foreach ($Tenant in $tenants) { + try { + $ExistingO365 = New-graphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps' -tenantid $tenant | Where-Object { $_.displayname -eq 'Microsoft 365 Apps for Windows 10 and later' } + if (!$ExistingO365) { + $Arch = if ($request.body.arch) { 'x64' } else { 'x86' } + $products = @('o365ProPlusRetail') + $ExcludedApps = [pscustomobject]@{ + infoPath = $true + sharePointDesigner = $true + excel = $false + lync = $false + oneNote = $false + outlook = $false + powerPoint = $false + publisher = $false + teams = $false + word = $false + access = $false + bing = $false + } + foreach ($ExcludedApp in $request.body.excludedApps.value) { + $ExcludedApps.$excludedapp = $true + } + $ObjBody = [pscustomobject]@{ + '@odata.type' = '#microsoft.graph.officeSuiteApp' + 'displayName' = 'Microsoft 365 Apps for Windows 10 and later' + 'description' = 'Microsoft 365 Apps for Windows 10 and later' + 'informationUrl' = 'https://products.office.com/en-us/explore-office-for-home' + 'isFeatured' = $true + 'publisher' = 'Microsoft' + 'notes' = '' + 'owner' = 'Microsoft' + 'autoAcceptEula' = [bool]$request.body.AcceptLicense + 'excludedApps' = $ExcludedApps + 'officePlatformArchitecture' = $Arch + 'officeSuiteAppDefaultFileFormat' = 'OfficeOpenXMLFormat' + 'localesToInstall' = @($request.body.languages.value) + 'shouldUninstallOlderVersionsOfOffice' = [bool]$request.body.RemoveVersions + 'updateChannel' = $request.body.updateChannel.value + 'useSharedComputerActivation' = [bool]$request.body.SharedComputerActivation + 'productIds' = $products + 'largeIcon' = @{ + 'type' = 'image/png' + 'value' = 'iVBORw0KGgoAAAANSUhEUgAAAF0AAAAeCAMAAAEOZNKlAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJhUExURf////7z7/i9qfF1S/KCW/i+qv3q5P/9/PrQwfOMae1RG+s8AOxGDfBtQPWhhPvUx/759/zg1vWgg+9fLu5WIvKFX/rSxP728/nCr/FyR+tBBvOMaO1UH+1RHOs+AvSScP3u6f/+/v3s5vzg1+xFDO9kNPOOa/i7pvzj2/vWyes9Af76+Pzh2PrTxf/6+f7y7vOGYexHDv3t5+1SHfi8qPOIZPvb0O1NFuxDCe9hMPSVdPnFs/3q4/vaz/STcu5VIe5YJPWcfv718v/9/e1MFfF4T/F4TvF2TP3o4exECvF0SexIEPONavzn3/vZze1QGvF3Te5dK+5cKvrPwPrQwvKAWe1OGPexmexKEveulfezm/BxRfamiuxLE/apj/zf1e5YJfSXd/OHYv3r5feznPakiPze1P7x7f739f3w6+xJEfnEsvWdf/Wfge1LFPe1nu9iMvnDsfBqPOs/BPOIY/WZevJ/V/zl3fnIt/vTxuxHD+xEC+9mN+5ZJv749vBpO/KBWvBwRP/8+/SUc/etlPjArP/7+vOLZ/F7UvWae/708e1OF/aihvSWdvi8p+tABfSZefvVyPWihfSVde9lNvami+9jM/zi2fKEXvBuQvOKZvalifF5UPJ/WPSPbe9eLfrKuvvd0uxBB/7w7Pzj2vrRw/rOv+1PGfi/q/eymu5bKf3n4PnJuPBrPf3t6PWfgvWegOxCCO9nOO9oOfaskvSYePi5pPi2oPnGtO5eLPevlvKDXfrNvv739Pzd0/708O9gL+9lNfJ9VfrLu/OPbPnDsPBrPus+A/nArfarkQAAAGr5HKgAAADLdFJOU/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AvuakogAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAz5JREFUOE+tVTtu4zAQHQjppmWzwIJbEVCzpTpjbxD3grQHSOXKRXgCAT6EC7UBVAmp3KwBnmvfzNCyZTmxgeTZJsXx43B+HBHRE34ZkXgkerXFTheeiCkRrbB4UXmp4wSWz5raaQEMTM5TZwuiXoaKgV+6FsmkZQcSy0kA71yMTMGHanX+AzMMGLAQCxU1F/ZwjULPugazl82GM0NEKm/U8EqFwEkO3/EAT4grgl0nucwlk9pcpTTJ4VPA4g/Rb3yIRhhp507e9nTQmZ1OS5RO4sS7nIRPEeHXCHdkw9ZEW2yVE5oIS7peD58Avs7CN+PVCmHh21oOqBdjDzIs+FldPJ74TFESUSJEfVzy9U/dhu+AuOT6eBp6gGKyXEx8euO450ZE4CMfstMFT44broWw/itkYErWXRx+fFArt9Ca9os78TFed0LVIUsmIHrwbwaw3BEOnOk94qVpQ6Ka2HjxewJnfyd6jUtGDQLdWlzmYNYLeKbbGOucJsNabCq1Yub0o92rtR+i30V2dapxYVEePXcOjeCKPnYyit7BtKeNlZqHbr+gt7i+AChWA9RsRs03pxTQc67ouWpxyESvjK5Vs3DVSy3IpkxPm5X+wZoBi+MFHWW69/w8FRhc7VBe6HAhMB2b8Q0XqDzTNZtXUMnKMjwKVaCrB/CSUL7WSx/HsdJC86lFGXwnioTeOMPjV+szlFvrZLA5VMVK4y+41l4e1xfx7Z88o4hkilRUH/qKqwNVlgDgpvYCpH3XwAy5eMCRnezIUxffVXoDql2rTHFDO+pjWnTWzAfrYXn6BFECblUpWGrvPZvBipETjS5ydM7tdXpH41ZCEbBNy/+wFZu71QO2t9pgT+iZEf657Q1vpN94PQNDxUHeKR103LV9nPVOtDikcNKO+2naCw7yKBhOe9Hm79pe8C4/CfC2wDjXnqC94kEeBU3WwN7dt/2UScXas7zDl5GpkY+M8WKv2J7fd4Ib2rGTk+jsC2cleEM7jI9veF7B0MBJrsZqfKd/81q9pR2NZfwJK2JzsmIT1Ns8jUH0UusQBpU8d2JzsHiXg1zXGLqxfitUNTDT/nUUeqDBp2HZVr+Ocqi/Ty3Rf4Jn82xxfSNtAAAAAElFTkSuQmCC' + } + } + Write-Host ($ObjBody | ConvertTo-Json -Compress) + $OfficeAppID = New-graphPostRequest -Uri 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps' -tenantid $tenant -Body (ConvertTo-Json -InputObject $ObjBody -Depth 10) -type POST } - foreach ($ExcludedApp in $request.body.excludedApps.value) { - $ExcludedApps.$excludedapp = $true + else { + "Office deployment already exists for $($Tenant)" + Continue } - $ObjBody = [pscustomobject]@{ - "@odata.type" = "#microsoft.graph.officeSuiteApp" - "displayName" = "Microsoft 365 Apps for Windows 10 and later" - "description" = "Microsoft 365 Apps for Windows 10 and later" - "informationUrl" = "https://products.office.com/en-us/explore-office-for-home" - "isFeatured" = $true - "publisher" = "Microsoft" - "notes" = "" - "owner" = "Microsoft" - "autoAcceptEula" = [bool]$request.body.AcceptLicense - "excludedApps" = $ExcludedApps - "officePlatformArchitecture" = $Arch - "officeSuiteAppDefaultFileFormat" = "OfficeOpenXMLFormat" - "localesToInstall" = @($request.body.languages.value) - "shouldUninstallOlderVersionsOfOffice" = [bool]$request.body.RemoveVersions - "updateChannel" = $request.body.updateChannel.value - "useSharedComputerActivation" = [bool]$request.body.SharedComputerActivation - "productIds" = $products - "largeIcon" = @{ - "type" = "image/png" - "value" = "iVBORw0KGgoAAAANSUhEUgAAAF0AAAAeCAMAAAEOZNKlAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJhUExURf////7z7/i9qfF1S/KCW/i+qv3q5P/9/PrQwfOMae1RG+s8AOxGDfBtQPWhhPvUx/759/zg1vWgg+9fLu5WIvKFX/rSxP728/nCr/FyR+tBBvOMaO1UH+1RHOs+AvSScP3u6f/+/v3s5vzg1+xFDO9kNPOOa/i7pvzj2/vWyes9Af76+Pzh2PrTxf/6+f7y7vOGYexHDv3t5+1SHfi8qPOIZPvb0O1NFuxDCe9hMPSVdPnFs/3q4/vaz/STcu5VIe5YJPWcfv718v/9/e1MFfF4T/F4TvF2TP3o4exECvF0SexIEPONavzn3/vZze1QGvF3Te5dK+5cKvrPwPrQwvKAWe1OGPexmexKEveulfezm/BxRfamiuxLE/apj/zf1e5YJfSXd/OHYv3r5feznPakiPze1P7x7f739f3w6+xJEfnEsvWdf/Wfge1LFPe1nu9iMvnDsfBqPOs/BPOIY/WZevJ/V/zl3fnIt/vTxuxHD+xEC+9mN+5ZJv749vBpO/KBWvBwRP/8+/SUc/etlPjArP/7+vOLZ/F7UvWae/708e1OF/aihvSWdvi8p+tABfSZefvVyPWihfSVde9lNvami+9jM/zi2fKEXvBuQvOKZvalifF5UPJ/WPSPbe9eLfrKuvvd0uxBB/7w7Pzj2vrRw/rOv+1PGfi/q/eymu5bKf3n4PnJuPBrPf3t6PWfgvWegOxCCO9nOO9oOfaskvSYePi5pPi2oPnGtO5eLPevlvKDXfrNvv739Pzd0/708O9gL+9lNfJ9VfrLu/OPbPnDsPBrPus+A/nArfarkQAAAGr5HKgAAADLdFJOU/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AvuakogAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAz5JREFUOE+tVTtu4zAQHQjppmWzwIJbEVCzpTpjbxD3grQHSOXKRXgCAT6EC7UBVAmp3KwBnmvfzNCyZTmxgeTZJsXx43B+HBHRE34ZkXgkerXFTheeiCkRrbB4UXmp4wSWz5raaQEMTM5TZwuiXoaKgV+6FsmkZQcSy0kA71yMTMGHanX+AzMMGLAQCxU1F/ZwjULPugazl82GM0NEKm/U8EqFwEkO3/EAT4grgl0nucwlk9pcpTTJ4VPA4g/Rb3yIRhhp507e9nTQmZ1OS5RO4sS7nIRPEeHXCHdkw9ZEW2yVE5oIS7peD58Avs7CN+PVCmHh21oOqBdjDzIs+FldPJ74TFESUSJEfVzy9U/dhu+AuOT6eBp6gGKyXEx8euO450ZE4CMfstMFT44broWw/itkYErWXRx+fFArt9Ca9os78TFed0LVIUsmIHrwbwaw3BEOnOk94qVpQ6Ka2HjxewJnfyd6jUtGDQLdWlzmYNYLeKbbGOucJsNabCq1Yub0o92rtR+i30V2dapxYVEePXcOjeCKPnYyit7BtKeNlZqHbr+gt7i+AChWA9RsRs03pxTQc67ouWpxyESvjK5Vs3DVSy3IpkxPm5X+wZoBi+MFHWW69/w8FRhc7VBe6HAhMB2b8Q0XqDzTNZtXUMnKMjwKVaCrB/CSUL7WSx/HsdJC86lFGXwnioTeOMPjV+szlFvrZLA5VMVK4y+41l4e1xfx7Z88o4hkilRUH/qKqwNVlgDgpvYCpH3XwAy5eMCRnezIUxffVXoDql2rTHFDO+pjWnTWzAfrYXn6BFECblUpWGrvPZvBipETjS5ydM7tdXpH41ZCEbBNy/+wFZu71QO2t9pgT+iZEf657Q1vpN94PQNDxUHeKR103LV9nPVOtDikcNKO+2naCw7yKBhOe9Hm79pe8C4/CfC2wDjXnqC94kEeBU3WwN7dt/2UScXas7zDl5GpkY+M8WKv2J7fd4Ib2rGTk+jsC2cleEM7jI9veF7B0MBJrsZqfKd/81q9pR2NZfwJK2JzsmIT1Ns8jUH0UusQBpU8d2JzsHiXg1zXGLqxfitUNTDT/nUUeqDBp2HZVr+Ocqi/Ty3Rf4Jn82xxfSNtAAAAAElFTkSuQmCC" - } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Added Office profile to $($tenant)" -Sev 'Info' + if ($AssignTo) { + $AssignO365 = if ($AssignTo -ne 'AllDevicesAndUsers') { '{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.' + $($AssignTo) + 'AssignmentTarget"},"intent":"Required"}]}' } else { '{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"},"intent":"Required"},{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"},"intent":"Required"}]}' } Write-Host ($AssignO365) + New-graphPostRequest -Uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($OfficeAppID.id)/assign" -tenantid $tenant -Body $AssignO365 -type POST + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Assigned Office to $AssignTo" -Sev 'Info' } - Write-Host ($ObjBody | ConvertTo-Json -Compress) - $OfficeAppID = New-graphPostRequest -Uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps" -tenantid $tenant -Body (ConvertTo-Json -InputObject $ObjBody -Depth 10) -type POST - } - else { - "Office deployment already exists for $($Tenant)" - Continue + "Successfully added Office App for $($Tenant)" } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Added Office profile to $($tenant)" -Sev "Info" - if ($AssignTo) { - $AssignO365 = if ($AssignTo -ne "AllDevicesAndUsers") { '{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.' + $($AssignTo) + 'AssignmentTarget"},"intent":"Required"}]}' } else { '{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"},"intent":"Required"},{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"},"intent":"Required"}]}' } Write-Host ($AssignO365) - New-graphPostRequest -Uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($OfficeAppID.id)/assign" -tenantid $tenant -Body $AssignO365 -type POST - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Assigned Office to $AssignTo" -Sev "Info" + catch { + "Failed to add Office App for $($Tenant): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Failed adding Autopilot Profile $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + continue } - "Successfully added Office Application for $($Tenant)" - } - catch { - "Failed to add Office App for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenant) -message "Failed adding Autopilot Profile $($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue - } -} + } -$body = [pscustomobject]@{"Results" = $results } + $body = [pscustomobject]@{'Results' = $results } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddPolicy.ps1 index 4884caffb04b..34a79bee6b7e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddPolicy.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddPolicy { +Function Invoke-AddPolicy { <# .FUNCTIONALITY Entrypoint @@ -8,75 +8,75 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -if ("AllTenants" -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } -$displayname = $request.body.Displayname -$description = $request.body.Description -$AssignTo = if ($request.body.Assignto -ne "on") { $request.body.Assignto } -$RawJSON = $Request.body.RawJSON + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } + $displayname = $request.body.Displayname + $description = $request.body.Description + $AssignTo = if ($request.body.Assignto -ne 'on') { $request.body.Assignto } + $RawJSON = $Request.body.RawJSON -$results = foreach ($Tenant in $tenants) { - if ($Request.body.replacemap.$tenant) { + $results = foreach ($Tenant in $tenants) { + if ($Request.body.replacemap.$tenant) { ([pscustomobject]$Request.body.replacemap.$tenant).psobject.properties | ForEach-Object { $RawJson = $RawJson -replace $_.name, $_.value } - } - try { - switch ($Request.body.TemplateType) { - "Admin" { - $TemplateTypeURL = "groupPolicyConfigurations" - $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($displayname -in $CheckExististing.displayName) { - Throw "Policy with Display Name $($Displayname) Already exists" - } - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $CreateBody - $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON - } - "Device" { - $TemplateTypeURL = "deviceConfigurations" - $PolicyName = ($RawJSON | ConvertFrom-Json).displayName - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - Write-Host $PolicyName - if ($PolicyName -in $CheckExististing.displayName) { - Throw "Policy with Display Name $($Displayname) Already exists" + } + try { + switch ($Request.body.TemplateType) { + 'Admin' { + $TemplateTypeURL = 'groupPolicyConfigurations' + $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($displayname -in $CheckExististing.displayName) { + Throw "Policy with Display Name $($Displayname) Already exists" + } + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $CreateBody + $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON } + 'Device' { + $TemplateTypeURL = 'deviceConfigurations' + $PolicyName = ($RawJSON | ConvertFrom-Json).displayName + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + Write-Host $PolicyName + if ($PolicyName -in $CheckExististing.displayName) { + Throw "Policy with Display Name $($Displayname) Already exists" + } - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - } - "Catalog" { - $TemplateTypeURL = "configurationPolicies" - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - $PolicyName = ($RawJSON | ConvertFrom-Json).Name - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($PolicyName -in $CheckExististing.name) { - Throw "Policy with Display Name $($Displayname) Already exists" + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + } + 'Catalog' { + $TemplateTypeURL = 'configurationPolicies' + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + $PolicyName = ($RawJSON | ConvertFrom-Json).Name + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($PolicyName -in $CheckExististing.name) { + Throw "Policy with Display Name $($Displayname) Already exists" + } + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON } - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - } + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname)" -Sev 'Info' + if ($AssignTo) { + Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -Type $TemplateTypeURL -TenantFilter $tenant + } + "Successfully added policy for $($Tenant)" } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname)" -Sev "Error" - if ($AssignTo) { - Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -Type $TemplateTypeURL -TenantFilter $tenant + catch { + "Failed to add policy for $($Tenant): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed adding policy $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + continue } - "Successfully added policy for $($Tenant)" - } - catch { - "Failed to add policy for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed adding policy $($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue - } -} + } -$body = [pscustomobject]@{"Results" = @($results) } + $body = [pscustomobject]@{'Results' = @($results) } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSharedMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSharedMailbox.ps1 index 32596817183b..7c3771c3264f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSharedMailbox.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddSharedMailbox { +Function Invoke-AddSharedMailbox { <# .FUNCTIONALITY Entrypoint @@ -8,40 +8,39 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$groupobj = $Request.body -$user = $request.headers.'x-ms-client-principal' + $groupobj = $Request.body -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." -try { + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + try { - $email = "$($groupobj.username)@$($groupobj.domain)" - $BodyToship = [pscustomobject] @{ - "displayName" = $groupobj.Displayname - "name" = $groupobj.username - "primarySMTPAddress" = $email - Shared = $true + $email = "$($groupobj.username)@$($groupobj.domain)" + $BodyToship = [pscustomobject] @{ + 'displayName' = $groupobj.Displayname + 'name' = $groupobj.username + 'primarySMTPAddress' = $email + Shared = $true - } - New-ExoRequest -tenantid $Request.body.tenantid -cmdlet "New-Mailbox" -cmdparams $BodyToship + } + New-ExoRequest -tenantid $Request.body.tenantid -cmdlet 'New-Mailbox' -cmdparams $BodyToship - $body = [pscustomobject]@{"Results" = "Successfully created shared mailbox." } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($groupobj.tenantid) -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) for " -Sev "Info" + $body = [pscustomobject]@{'Results' = 'Successfully created shared mailbox.' } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($groupobj.tenantid) -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) for " -Sev 'Info' -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($groupobj.tenantid) -message "Group creation API failed. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to create group. $($_.Exception.Message)" } + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($groupobj.tenantid) -message "Group creation API failed. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to create group. $($_.Exception.Message)" } -} + } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilter.ps1 index e9be0668bd97..789b3eaffe9d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilter.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddSpamFilter { +Function Invoke-AddSpamFilter { <# .FUNCTIONALITY Entrypoint @@ -9,36 +9,36 @@ param($Request, $TriggerMetadata) -$APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, comments + $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, comments -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -$Result = foreach ($Tenantfilter in $tenants) { - try { - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-HostedContentFilterPolicy" -cmdParams $RequestParams - $Domains = (New-ExoRequest -tenantid $Tenantfilter -cmdlet "Get-AcceptedDomain").name - $ruleparams = @{ - "name" = "$($RequestParams.name)"; - "hostedcontentfilterpolicy" = "$($RequestParams.name)"; - "recipientdomainis" = @($domains) - "Enabled" = $true + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $Result = foreach ($Tenantfilter in $tenants) { + try { + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'New-HostedContentFilterPolicy' -cmdParams $RequestParams + $Domains = (New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-AcceptedDomain').name + $ruleparams = @{ + 'name' = "$($RequestParams.name)" + 'hostedcontentfilterpolicy' = "$($RequestParams.name)" + 'recipientdomainis' = @($domains) + 'Enabled' = $true + } + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'New-HostedContentFilterRule' -cmdParams $ruleparams + "Successfully created spamfilter for $tenantfilter." + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Created spamfilter rule for $($tenantfilter)" -sev Info + } + catch { + "Could not create create spamfilter rule for $($tenantfilter): $($_.Exception.message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Could not create create spamfilter rule for $($tenantfilter): $($_.Exception.message)" -sev Error } - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-HostedContentFilterRule" -cmdParams $ruleparams - "Successfully created spamfilter for $tenantfilter." - Write-LogMessage -API $APINAME -tenant $tenantfilter -message "Created spamfilter for $($tenantfilter)" -sev Debug - } - catch { - "Could not create create spamfilter rule for $($tenantfilter): $($_.Exception.message)" } -} - -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{Results = @($Result) } - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{Results = @($Result) } + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilterTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilterTemplate.ps1 index 45fae4ecbfc0..9aeef51f243c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilterTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddSpamFilterTemplate.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddSpamFilterTemplate { +Function Invoke-AddSpamFilterTemplate { <# .FUNCTIONALITY Entrypoint @@ -8,44 +8,44 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -Write-Host ($request | ConvertTo-Json -Compress) + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + Write-Host ($request | ConvertTo-Json -Compress) -try { - $GUID = (New-Guid).GUID - $JSON = if ($request.body.PowerShellCommand) { - Write-Host "PowerShellCommand" - $request.body.PowerShellCommand | ConvertFrom-Json - } - else { + try { + $GUID = (New-Guid).GUID + $JSON = if ($request.body.PowerShellCommand) { + Write-Host 'PowerShellCommand' + $request.body.PowerShellCommand | ConvertFrom-Json + } + else { ([pscustomobject]$Request.body | Select-Object name, AddXHeaderValue, AdminDisplayName, AllowedSenderDomains, AllowedSenders, BlockedSenderDomains, BlockedSenders, BulkQuarantineTag, BulkSpamAction, BulkThreshold, Confirm, DownloadLink, EnableEndUserSpamNotifications, EnableLanguageBlockList, EnableRegionBlockList, EndUserSpamNotificationCustomFromAddress, EndUserSpamNotificationCustomFromName, EndUserSpamNotificationCustomSubject, EndUserSpamNotificationFrequency, EndUserSpamNotificationLanguage, EndUserSpamNotificationLimit, HighConfidencePhishAction, HighConfidencePhishQuarantineTag, HighConfidenceSpamAction, HighConfidenceSpamQuarantineTag, IncreaseScoreWithBizOrInfoUrls, IncreaseScoreWithImageLinks, IncreaseScoreWithNumericIps, IncreaseScoreWithRedirectToOtherPort, InlineSafetyTipsEnabled, LanguageBlockList, MarkAsSpamBulkMail, MarkAsSpamEmbedTagsInHtml, MarkAsSpamEmptyMessages, MarkAsSpamFormTagsInHtml, MarkAsSpamFramesInHtml, MarkAsSpamFromAddressAuthFail, MarkAsSpamJavaScriptInHtml, MarkAsSpamNdrBackscatter, MarkAsSpamObjectTagsInHtml, MarkAsSpamSensitiveWordList, MarkAsSpamSpfRecordHardFail, MarkAsSpamWebBugsInHtml, ModifySubjectValue, PhishQuarantineTag, PhishSpamAction, PhishZapEnabled, QuarantineRetentionPeriod, RecommendedPolicyType, RedirectToRecipients, RegionBlockList, SpamAction, SpamQuarantineTag, SpamZapEnabled, TestModeAction, TestModeBccToRecipients ) | ForEach-Object { - $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name - $_ | Select-Object -Property $NonEmptyProperties + $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name + $_ | Select-Object -Property $NonEmptyProperties + } + } + $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10) + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$json" + RowKey = "$GUID" + PartitionKey = 'SpamfilterTemplate' } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Spam Filter Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' + $body = [pscustomobject]@{'Results' = 'Successfully added template' } + } - $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10) - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$json" - RowKey = "$GUID" - PartitionKey = "SpamfilterTemplate" + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Spam Filter Template: $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Spamfilter Template Deployment failed: $($_.Exception.Message)" } } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Spam Filter Template $($Request.body.name) with GUID $GUID" -Sev "Debug" - $body = [pscustomobject]@{"Results" = "Successfully added template" } - -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Spam Filter Template: $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Spamfilter Template Deployment failed: $($_.Exception.Message)" } -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddStandardsDeploy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddStandardsDeploy.ps1 index fda5dbc33053..4a849d960ac9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddStandardsDeploy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddStandardsDeploy.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddStandardsDeploy { +Function Invoke-AddStandardsDeploy { <# .FUNCTIONALITY Entrypoint @@ -8,43 +8,46 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$user = $request.headers.'x-ms-client-principal' -$username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($user)) | ConvertFrom-Json).userDetails + $user = $request.headers.'x-ms-client-principal' + $username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($user)) | ConvertFrom-Json).userDetails -try { - $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value - $Settings = ($request.body | Select-Object -Property * -ExcludeProperty Select_*, None ) - foreach ($Tenant in $tenants) { + try { + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $Settings = ($request.body | Select-Object -Property *, v2* -ExcludeProperty Select_*, None ) + $Settings | Add-Member -NotePropertyName 'v2.1' -NotePropertyValue $true -Force + foreach ($Tenant in $tenants) { - $object = [PSCustomObject]@{ - Tenant = $tenant - AddedBy = $username - AppliedAt = (Get-Date).ToString('s') - Standards = $Settings - } | ConvertTo-Json -Depth 10 - $Table = Get-CippTable -tablename 'standards' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$object" - RowKey = "$Tenant" - PartitionKey = "standards" + $object = [PSCustomObject]@{ + Tenant = $tenant + AddedBy = $username + AppliedAt = (Get-Date).ToString('s') + Standards = $Settings + v2 = $true + } | ConvertTo-Json -Depth 10 + $Table = Get-CippTable -tablename 'standards' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$object" + RowKey = "$Tenant" + PartitionKey = 'standards' + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -tenant $tenant -API 'Standards' -message 'Successfully added standards deployment' -Sev 'Info' } + $body = [pscustomobject]@{'Results' = 'Successfully added standards deployment' } + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Standards' -message "Standards API failed. Error:$($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to add standard: $($_.Exception.Message)" } } - $body = [pscustomobject]@{"Results" = "Successfully added standards deployment" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Standards API failed. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to add standard: $($_.Exception.Message)" } -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTeam.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTeam.ps1 index d11998bc4260..34b9bda58208 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTeam.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTeam.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddTeam { +Function Invoke-AddTeam { <# .FUNCTIONALITY Entrypoint @@ -8,51 +8,51 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$userobj = $Request.body + $userobj = $Request.body -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." - -$Owners = ($userobj.owner).Split([Environment]::NewLine) | Where-Object { $_ -ne $null -or $_ -ne "" } -try { + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + + $Owners = ($userobj.owner).Split([Environment]::NewLine) | Where-Object { $_ -ne $null -or $_ -ne '' } + try { - $Owners = $Owners | ForEach-Object { - $OwnerID = "https://graph.microsoft.com/beta/users('" + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$_" -tenantid $Userobj.tenantid).id + "')" - @{ - "@odata.type" = "#microsoft.graph.aadUserConversationMember" - "roles" = @("owner") - "user@odata.bind" = $OwnerID + $Owners = $Owners | ForEach-Object { + $OwnerID = "https://graph.microsoft.com/beta/users('" + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$_" -tenantid $Userobj.tenantid).id + "')" + @{ + '@odata.type' = '#microsoft.graph.aadUserConversationMember' + 'roles' = @('owner') + 'user@odata.bind' = $OwnerID + } } - } - $TeamsSettings = [PSCustomObject]@{ - "template@odata.bind" = "https://graph.microsoft.com/v1.0/teamsTemplates('standard')" - "visibility" = $userobj.visibility - "displayName" = $userobj.displayname - "description" = $userobj.description - "members" = @($owners) + $TeamsSettings = [PSCustomObject]@{ + 'template@odata.bind' = "https://graph.microsoft.com/v1.0/teamsTemplates('standard')" + 'visibility' = $userobj.visibility + 'displayName' = $userobj.displayname + 'description' = $userobj.description + 'members' = @($owners) - } | ConvertTo-Json -Depth 10 + } | ConvertTo-Json -Depth 10 - Write-Host $TeamsSettings - New-GraphPostRequest -AsApp $true -uri "https://graph.microsoft.com/beta/teams" -tenantid $Userobj.tenantid -type POST -body $TeamsSettings -verbose - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Added Team $($userobj.displayname)" -Sev "Info" - $body = [pscustomobject]@{"Results" = "Success. Team has been added" } + Write-Host $TeamsSettings + New-GraphPostRequest -AsApp $true -uri 'https://graph.microsoft.com/beta/teams' -tenantid $Userobj.tenantid -type POST -body $TeamsSettings -verbose + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Added Team $($userobj.displayname)" -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Success. Team has been added' } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "$($userobj.tenantid): Add Team failed. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed. Error message: $($_.Exception.Message)" } -} + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Adding Team failed. Error: $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed. Error message: $($_.Exception.Message)" } + } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportRule.ps1 index 4a5ddf22abbc..64c394ee2852 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportRule.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportRule.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddTransportRule { +Function Invoke-AddTransportRule { <# .FUNCTIONALITY Entrypoint @@ -8,39 +8,39 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications + $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -$Result = foreach ($Tenantfilter in $tenants) { - $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenantfilter -cmdlet "Get-TransportRule" -useSystemMailbox $true | Where-Object -Property Identity -EQ $RequestParams.name - try { - if ($Existing) { - Write-Host "Found existing" - $RequestParams | Add-Member -NotePropertyValue $RequestParams.name -NotePropertyName Identity - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "Set-TransportRule" -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty UseLegacyRegex) -useSystemMailbox $true - "Successfully set transport rule for $tenantfilter." + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $Result = foreach ($Tenantfilter in $tenants) { + $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenantfilter -cmdlet 'Get-TransportRule' -useSystemMailbox $true | Where-Object -Property Identity -EQ $RequestParams.name + try { + if ($Existing) { + Write-Host 'Found existing' + $RequestParams | Add-Member -NotePropertyValue $RequestParams.name -NotePropertyName Identity + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Set-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty UseLegacyRegex) -useSystemMailbox $true + "Successfully set transport rule for $tenantfilter." + } + else { + Write-Host 'Creating new' + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'New-TransportRule' -cmdParams $RequestParams -useSystemMailbox $true + "Successfully created transport rule for $tenantfilter." + } + + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Created transport rule for $($tenantfilter)" -sev Info } - else { - Write-Host "Creating new" - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-TransportRule" -cmdParams $RequestParams -useSystemMailbox $true - "Successfully created transport rule for $tenantfilter." + catch { + "Could not create transport rule for $($tenantfilter): $($_.Exception.message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Could not create transport rule for $($tenantfilter). Error:$($_.Exception.message)" -sev Error } - - Write-LogMessage -API $APINAME -tenant $tenantfilter -message "Created transport rule for $($tenantfilter)" -sev Debug - } - catch { - "Could not create transport rule for $($tenantfilter): $($_.Exception.message)" } -} - -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{Results = @($Result) } - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{Results = @($Result) } + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportTemplate.ps1 index 43d8b28b13cd..6028c15578b6 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTransportTemplate.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddTransportTemplate { +Function Invoke-AddTransportTemplate { <# .FUNCTIONALITY Entrypoint @@ -8,44 +8,44 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -Write-Host ($request | ConvertTo-Json -Compress) + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + Write-Host ($request | ConvertTo-Json -Compress) -try { - $GUID = (New-Guid).GUID - $JSON = if ($request.body.PowerShellCommand) { - Write-Host "PowerShellCommand" - $request.body.PowerShellCommand | ConvertFrom-Json - } - else { + try { + $GUID = (New-Guid).GUID + $JSON = if ($request.body.PowerShellCommand) { + Write-Host 'PowerShellCommand' + $request.body.PowerShellCommand | ConvertFrom-Json + } + else { ([pscustomobject]$Request.body | Select-Object Name, ActivationDate, ADComparisonAttribute, ADComparisonOperator, AddManagerAsRecipientType, AddToRecipients, AnyOfCcHeader, AnyOfCcHeaderMemberOf, AnyOfRecipientAddressContainsWords, AnyOfRecipientAddressMatchesPatterns, AnyOfToCcHeader, AnyOfToCcHeaderMemberOf, AnyOfToHeader, AnyOfToHeaderMemberOf, ApplyClassification, ApplyHtmlDisclaimerFallbackAction, ApplyHtmlDisclaimerLocation, ApplyHtmlDisclaimerText, ApplyOME, ApplyRightsProtectionCustomizationTemplate, ApplyRightsProtectionTemplate, AttachmentContainsWords, AttachmentExtensionMatchesWords, AttachmentHasExecutableContent, AttachmentIsPasswordProtected, AttachmentIsUnsupported, AttachmentMatchesPatterns, AttachmentNameMatchesPatterns, AttachmentProcessingLimitExceeded, AttachmentPropertyContainsWords, AttachmentSizeOver, BetweenMemberOf1, BetweenMemberOf2, BlindCopyTo, Comments, Confirm, ContentCharacterSetContainsWords, CopyTo, DeleteMessage, DlpPolicy, DomainController, Enabled, ExceptIfADComparisonAttribute, ExceptIfADComparisonOperator, ExceptIfAnyOfCcHeader, ExceptIfAnyOfCcHeaderMemberOf, ExceptIfAnyOfRecipientAddressContainsWords, ExceptIfAnyOfRecipientAddressMatchesPatterns, ExceptIfAnyOfToCcHeader, ExceptIfAnyOfToCcHeaderMemberOf, ExceptIfAnyOfToHeader, ExceptIfAnyOfToHeaderMemberOf, ExceptIfAttachmentContainsWords, ExceptIfAttachmentExtensionMatchesWords, ExceptIfAttachmentHasExecutableContent, ExceptIfAttachmentIsPasswordProtected, ExceptIfAttachmentIsUnsupported, ExceptIfAttachmentMatchesPatterns, ExceptIfAttachmentNameMatchesPatterns, ExceptIfAttachmentProcessingLimitExceeded, ExceptIfAttachmentPropertyContainsWords, ExceptIfAttachmentSizeOver, ExceptIfBetweenMemberOf1, ExceptIfBetweenMemberOf2, ExceptIfContentCharacterSetContainsWords, ExceptIfFrom, ExceptIfFromAddressContainsWords, ExceptIfFromAddressMatchesPatterns, ExceptIfFromMemberOf, ExceptIfFromScope, ExceptIfHasClassification, ExceptIfHasNoClassification, ExceptIfHasSenderOverride, ExceptIfHeaderContainsMessageHeader, ExceptIfHeaderContainsWords, ExceptIfHeaderMatchesMessageHeader, ExceptIfHeaderMatchesPatterns, ExceptIfManagerAddresses, ExceptIfManagerForEvaluatedUser, ExceptIfMessageContainsDataClassifications, ExceptIfMessageSizeOver, ExceptIfMessageTypeMatches, ExceptIfRecipientADAttributeContainsWords, ExceptIfRecipientADAttributeMatchesPatterns, ExceptIfRecipientAddressContainsWords, ExceptIfRecipientAddressMatchesPatterns, ExceptIfRecipientDomainIs, ExceptIfRecipientInSenderList, ExceptIfSCLOver, ExceptIfSenderADAttributeContainsWords, ExceptIfSenderADAttributeMatchesPatterns, ExceptIfSenderDomainIs, ExceptIfSenderInRecipientList, ExceptIfSenderIpRanges, ExceptIfSenderManagementRelationship, ExceptIfSentTo, ExceptIfSentToMemberOf, ExceptIfSentToScope, ExceptIfSubjectContainsWords, ExceptIfSubjectMatchesPatterns, ExceptIfSubjectOrBodyContainsWords, ExceptIfSubjectOrBodyMatchesPatterns, ExceptIfWithImportance, ExpiryDate, From, FromAddressContainsWords, FromAddressMatchesPatterns, FromMemberOf, FromScope, GenerateIncidentReport, GenerateNotification, HasClassification, HasNoClassification, HasSenderOverride, HeaderContainsMessageHeader, HeaderContainsWords, HeaderMatchesMessageHeader, HeaderMatchesPatterns, IncidentReportContent, IncidentReportOriginalMail, LogEventText, ManagerAddresses, ManagerForEvaluatedUser, MessageContainsDataClassifications, MessageSizeOver, MessageTypeMatches, Mode, ModerateMessageByManager, ModerateMessageByUser, NotifySender, PrependSubject, Quarantine, RecipientADAttributeContainsWords, RecipientADAttributeMatchesPatterns, RecipientAddressContainsWords, RecipientAddressMatchesPatterns, RecipientAddressType, RecipientDomainIs, RecipientInSenderList, RedirectMessageTo, RejectMessageEnhancedStatusCode, RejectMessageReasonText, RemoveHeader, RemoveOME, RemoveOMEv2, RemoveRMSAttachmentEncryption, RouteMessageOutboundConnector, RouteMessageOutboundRequireTls, RuleErrorAction, RuleSubType, SCLOver, SenderADAttributeContainsWords, SenderADAttributeMatchesPatterns, SenderAddressLocation, SenderDomainIs, SenderInRecipientList, SenderIpRanges, SenderManagementRelationship, SentTo, SentToMemberOf, SentToScope, SetAuditSeverity, SetHeaderName, SetHeaderValue, SetSCL, SmtpRejectMessageRejectStatusCode, SmtpRejectMessageRejectText, StopRuleProcessing, SubjectContainsWords, SubjectMatchesPatterns, SubjectOrBodyContainsWords, SubjectOrBodyMatchesPatterns, UseLegacyRegex, WithImportance ) | ForEach-Object { - $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name - $_ | Select-Object -Property $NonEmptyProperties + $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name + $_ | Select-Object -Property $NonEmptyProperties + } + } + $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10) + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$json" + RowKey = "$GUID" + PartitionKey = 'TransportTemplate' } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Transport Rule Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' + $body = [pscustomobject]@{'Results' = 'Successfully added template' } + } - $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10) - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$json" - RowKey = "$GUID" - PartitionKey = "TransportTemplate" + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Transport Rule Template: $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Intune Template Deployment failed: $($_.Exception.Message)" } } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Transport Rule Template $($Request.body.name) with GUID $GUID" -Sev "Debug" - $body = [pscustomobject]@{"Results" = "Successfully added template" } - -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Transport Rule Template: $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Intune Template Deployment failed: $($_.Exception.Message)" } -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddUser.ps1 index f9eb6ba28546..1e6888622537 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddUser.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddUser { +Function Invoke-AddUser { <# .FUNCTIONALITY Entrypoint @@ -8,114 +8,115 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -$Results = [System.Collections.ArrayList]@() -$userobj = $Request.body -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." -try { - $license = $userobj.license - $Aliases = ($userobj.AddedAliases).Split([Environment]::NewLine) - $password = if ($userobj.password) { $userobj.password } else { New-passwordString } - $UserprincipalName = "$($UserObj.username)@$($UserObj.domain)" - $BodyToship = [pscustomobject] @{ - "givenName" = $userobj.firstname - "surname" = $userobj.lastname - "accountEnabled" = $true - "displayName" = $UserObj.Displayname - "department" = $userobj.department - "mailNickname" = $UserObj.username - "userPrincipalName" = $UserprincipalName - "usageLocation" = $UserObj.usageLocation - "city" = $userobj.city - "country" = $userobj.country - "jobtitle" = $userObj.jobtitle - "mobilePhone" = $userobj.mobilePhone - "streetAddress" = $userobj.streetAddress - "postalCode" = $userobj.postalCode - "companyName" = $userobj.companyName - "passwordProfile" = @{ - "forceChangePasswordNextSignIn" = [bool]$UserObj.mustchangepass - "password" = $password - } - } - if ($userobj.businessPhone) { $bodytoShip | Add-Member -NotePropertyName businessPhones -NotePropertyValue @($userobj.businessPhone) } - if ($userobj.addedAttributes) { - Write-Host "Found added attribute" - Write-Host "Added attributes: $($userobj.addedAttributes | ConvertTo-Json)" - $userobj.addedAttributes.getenumerator() | ForEach-Object { - $results.add("Added property $($_.Key) with value $($_.value)") - $bodytoShip | Add-Member -NotePropertyName $_.Key -NotePropertyValue $_.Value + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + $Results = [System.Collections.ArrayList]@() + $userobj = $Request.body + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + try { + $license = $userobj.license + $Aliases = ($userobj.AddedAliases).Split([Environment]::NewLine) + $password = if ($userobj.password) { $userobj.password } else { New-passwordString } + $UserprincipalName = "$($UserObj.username)@$($UserObj.domain)" + $BodyToship = [pscustomobject] @{ + 'givenName' = $userobj.firstname + 'surname' = $userobj.lastname + 'accountEnabled' = $true + 'displayName' = $UserObj.Displayname + 'department' = $userobj.department + 'mailNickname' = $UserObj.username + 'userPrincipalName' = $UserprincipalName + 'usageLocation' = $UserObj.usageLocation + 'city' = $userobj.city + 'country' = $userobj.country + 'jobtitle' = $userObj.jobtitle + 'mobilePhone' = $userobj.mobilePhone + 'streetAddress' = $userobj.streetAddress + 'postalCode' = $userobj.postalCode + 'companyName' = $userobj.companyName + 'passwordProfile' = @{ + 'forceChangePasswordNextSignIn' = [bool]$UserObj.mustchangepass + 'password' = $password + } + } + if ($userobj.businessPhone) { $bodytoShip | Add-Member -NotePropertyName businessPhones -NotePropertyValue @($userobj.businessPhone) } + if ($userobj.addedAttributes) { + Write-Host 'Found added attribute' + Write-Host "Added attributes: $($userobj.addedAttributes | ConvertTo-Json)" + $userobj.addedAttributes.getenumerator() | ForEach-Object { + $results.add("Added property $($_.Key) with value $($_.value)") + $bodytoShip | Add-Member -NotePropertyName $_.Key -NotePropertyValue $_.Value + } } + $bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress + $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/users' -tenantid $Userobj.tenantid -type POST -body $BodyToship -verbose + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Created user $($userobj.displayname) with id $($GraphRequest.id) " -Sev 'Info' + $results.add('Created user.') + $results.add("Username: $($UserprincipalName)") + $results.add("Password: $password") + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Failed to create user. Error:$($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Failed to create user. $($_.Exception.Message)" ) } - $bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users" -tenantid $Userobj.tenantid -type POST -body $BodyToship -verbose - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Created user $($userobj.displayname) with id $($GraphRequest.id) " -Sev "Info" - $results.add("Created user.") - $results.add("Username: $($UserprincipalName)") - $results.add("Password: $password") -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "User creation API failed. $($_.Exception.Message)" -Sev "Error" - $body = $results.add("Failed to create user. $($_.Exception.Message)" ) -} -try { - if ($license) { - Write-Host ($userobj | ConvertTo-Json) - $licenses = (($userobj | Select-Object "License_*").psobject.properties | Where-Object { $_.value -EQ $true }).name -replace "License_", "" - Write-Host "Lics are: $licences" - $LicenseBody = if ($licenses.count -ge 2) { - $liclist = foreach ($license in $Licenses) { '{"disabledPlans": [],"skuId": "' + $license + '" },' } - '{"addLicenses": [' + $LicList + '], "removeLicenses": [ ] }' + try { + if ($license) { + Write-Host ($userobj | ConvertTo-Json) + $licenses = (($userobj | Select-Object 'License_*').psobject.properties | Where-Object { $_.value -EQ $true }).name -replace 'License_', '' + Write-Host "Lics are: $licences" + $LicenseBody = if ($licenses.count -ge 2) { + $liclist = foreach ($license in $Licenses) { '{"disabledPlans": [],"skuId": "' + $license + '" },' } + '{"addLicenses": [' + $LicList + '], "removeLicenses": [ ] }' + } + else { + '{"addLicenses": [ {"disabledPlans": [],"skuId": "' + $licenses + '" }],"removeLicenses": [ ]}' + } + Write-Host $LicenseBody + $LicRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($GraphRequest.id)/assignlicense" -tenantid $Userobj.tenantid -type POST -body $LicenseBody -verbose + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Assigned user $($userobj.displayname) license $($licences)" -Sev 'Info' + $body = $results.add('Assigned licenses.') } - else { - '{"addLicenses": [ {"disabledPlans": [],"skuId": "' + $licenses + '" }],"removeLicenses": [ ]}' - } - Write-Host $LicenseBody - $LicRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($GraphRequest.id)/assignlicense" -tenantid $Userobj.tenantid -type POST -body $LicenseBody -verbose - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Assigned user $($userobj.displayname) license $($licences)" -Sev "Info" - $body = $results.add("Assigned licenses.") - } -} + } -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "License assign API failed. $($_.Exception.Message)" -Sev "Error" - $body = $results.add("We've failed to assign the license. $($_.Exception.Message)") -} + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Failed to assign the license. Error:$($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Failed to assign the license. $($_.Exception.Message)") + } -try { - if ($Aliases) { - foreach ($Alias in $Aliases) { - Write-Host $Alias - New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($GraphRequest.id)" -tenantid $Userobj.tenantid -type "patch" -body "{`"mail`": `"$Alias`"}" -verbose + try { + if ($Aliases) { + foreach ($Alias in $Aliases) { + Write-Host $Alias + New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($GraphRequest.id)" -tenantid $Userobj.tenantid -type 'patch' -body "{`"mail`": `"$Alias`"}" -verbose + } + New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($GraphRequest.id)" -tenantid $Userobj.tenantid -type 'patch' -body "{`"mail`": `"$UserprincipalName`"}" -verbose + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Added alias $($Alias) to $($userobj.displayname)" -Sev 'Info' + $body = $results.add("Added Aliases: $($Aliases -join ',')") } - New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($GraphRequest.id)" -tenantid $Userobj.tenantid -type "patch" -body "{`"mail`": `"$UserprincipalName`"}" -verbose - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Added alias $($Alias) to $($userobj.displayname)" -Sev "Info" - $body = $results.add("Added Aliases: $($Aliases -join ',')") } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Alias API failed. $($_.Exception.Message)" -Sev "Error" - $body = $results.add("We've failed to create the Aliases: $($_.Exception.Message)") -} -if ($Request.body.CopyFrom -ne "") { - $CopyFrom = Set-CIPPCopyGroupMembers -ExecutingUser $request.headers.'x-ms-client-principal' -tenantid $Userobj.tenantid -CopyFromId $Request.body.CopyFrom -UserID $UserprincipalName -TenantFilter $Userobj.tenantid - $results.Add($CopyFrom.Success -join ', ') - $results.Add($CopyFrom.Error -join ', ') -} -$body = [pscustomobject] @{ - "Results" = @($results) - "Username" = $UserprincipalName - "Password" = $password - "CopyFrom" = $CopyFrom -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) - + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Failed to create the Aliases. Error:$($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Failed to create the Aliases: $($_.Exception.Message)") + } + if ($Request.body.CopyFrom -ne '') { + $CopyFrom = Set-CIPPCopyGroupMembers -ExecutingUser $request.headers.'x-ms-client-principal' -tenantid $Userobj.tenantid -CopyFromId $Request.body.CopyFrom -UserID $UserprincipalName -TenantFilter $Userobj.tenantid + $results.Add($CopyFrom.Success -join ', ') + $results.Add($CopyFrom.Error -join ', ') + } + $body = [pscustomobject] @{ + 'Results' = @($results) + 'Username' = $UserprincipalName + 'Password' = $password + 'CopyFrom' = $CopyFrom } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddWinGetApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddWinGetApp.ps1 index be59d93845f4..508484dfeb6c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddWinGetApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddWinGetApp.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-AddWinGetApp { +Function Invoke-AddWinGetApp { <# .FUNCTIONALITY Entrypoint @@ -8,58 +8,58 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -Write-Host "PowerShell HTTP trigger function processed a request." -$WinGetApp = $request.body -if ($ChocoApp.InstallAsSystem) { "system" } else { "user" } -$assignTo = $Request.body.AssignTo -$WinGetData = [ordered]@{ - "@odata.type" = "#microsoft.graph.winGetApp" - "displayName" = "$($WinGetApp.ApplicationName)" - "description" = "$($WinGetApp.description)" - "packageIdentifier" = "$($WinGetApp.PackageName)" - "installExperience" = @{ - "@odata.type" = "microsoft.graph.winGetAppInstallExperience" - "runAsAccount" = "user" + Write-Host 'PowerShell HTTP trigger function processed a request.' + $WinGetApp = $request.body + if ($ChocoApp.InstallAsSystem) { 'system' } else { 'user' } + $assignTo = $Request.body.AssignTo + $WinGetData = [ordered]@{ + '@odata.type' = '#microsoft.graph.winGetApp' + 'displayName' = "$($WinGetApp.ApplicationName)" + 'description' = "$($WinGetApp.description)" + 'packageIdentifier' = "$($WinGetApp.PackageName)" + 'installExperience' = @{ + '@odata.type' = 'microsoft.graph.winGetAppInstallExperience' + 'runAsAccount' = 'user' + } } -} -$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value -$Results = foreach ($Tenant in $tenants) { - try { - $CompleteObject = [PSCustomObject]@{ - tenant = $tenant - Applicationname = $WinGetApp.ApplicationName - assignTo = $assignTo - InstallationIntent = $request.body.InstallationIntent - type = 'WinGet' - IntuneBody = $WinGetData - } | ConvertTo-Json -Depth 15 - $Table = Get-CippTable -tablename 'apps' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$CompleteObject" - RowKey = "$((New-Guid).GUID)" - PartitionKey = "apps" - status = "Not Deployed yet" + $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value + $Results = foreach ($Tenant in $tenants) { + try { + $CompleteObject = [PSCustomObject]@{ + tenant = $tenant + Applicationname = $WinGetApp.ApplicationName + assignTo = $assignTo + InstallationIntent = $request.body.InstallationIntent + type = 'WinGet' + IntuneBody = $WinGetData + } | ConvertTo-Json -Depth 15 + $Table = Get-CippTable -tablename 'apps' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$CompleteObject" + RowKey = "$((New-Guid).GUID)" + PartitionKey = 'apps' + status = 'Not Deployed yet' + } + "Successfully added Store App for $($Tenant) to queue." + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Chocolatey Application $($intunebody.Displayname) queued to add" -Sev 'Info' + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed to add Chocolatey Application $($intunebody.Displayname) to queue" -Sev 'Error' + "Failed added Store App for $($Tenant) to queue" } - "Successfully added Store App for $($Tenant) to queue." - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Chocolatey Application $($intunebody.Displayname) queued to add" -Sev "Info" - } - catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Failed to add Chocolatey Application $($intunebody.Displayname) to queue" -Sev "Error" - "Failed added Store App for $($Tenant) to queue" } -} -$body = [pscustomobject]@{"Results" = $results } + $body = [pscustomobject]@{'Results' = $results } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-BestPracticeAnalyser_List.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-BestPracticeAnalyser_List.ps1 index 82f02778a5f2..e1930a1cbc04 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-BestPracticeAnalyser_List.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-BestPracticeAnalyser_List.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-BestPracticeAnalyser_List { +Function Invoke-BestPracticeAnalyser_List { <# .FUNCTIONALITY Entrypoint @@ -8,26 +8,26 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$Tenants = Get-Tenants -$Table = get-cipptable 'cachebpa' -$Results = (Get-CIPPAzDataTableEntity @Table) | ForEach-Object { - $_.UnusedLicenseList = @(ConvertFrom-Json -ErrorAction silentlycontinue -InputObject $_.UnusedLicenseList) - $_ -} - -if (!$Results) { - $Results = @{ - Tenant = "The BPA has not yet run." + $Tenants = Get-Tenants + $Table = get-cipptable 'cachebpa' + $Results = (Get-CIPPAzDataTableEntity @Table) | ForEach-Object { + $_.UnusedLicenseList = @(ConvertFrom-Json -ErrorAction silentlycontinue -InputObject $_.UnusedLicenseList) + $_ } -} -Write-Host ($Tenants | ConvertTo-Json) -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @(($Results | Where-Object -Property RowKey -In $Tenants.customerId)) - }) + if (!$Results) { + $Results = @{ + Tenant = 'The BPA has not yet run.' + } } + Write-Host ($Tenants | ConvertTo-Json) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @(($Results | Where-Object -Property RowKey -In $Tenants.customerId)) + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditCAPolicy.ps1 index da71838797bc..fb804f8fbfe1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditCAPolicy.ps1 @@ -16,9 +16,10 @@ Function Invoke-EditCAPolicy { $results = try { $EditBody = "{`"state`": `"$($request.query.state)`"}" $Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta//identity/conditionalAccess/policies/$($id)" -tenantid $tenant -type PATCH -body $EditBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Edited CA policy $($ID)" -Sev 'Error' - 'Successfully edited CA policy' - } catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Edited CA policy: $($ID)" -Sev 'Info' + "Successfully edited CA policy: $($ID)" + } + catch { "Failed to add CA policy: $($_.Exception.Message)" Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed editing CA policy $($ID). Error: $($_.Exception.Message)" -Sev 'Error' continue diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditExConnector.ps1 index 89a13dbb80bc..9042e7fdfa0a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditExConnector.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditExConnector.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-EditExConnector { +Function Invoke-EditExConnector { <# .FUNCTIONALITY Entrypoint @@ -8,30 +8,31 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -$Tenantfilter = $request.Query.tenantfilter + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Tenantfilter = $request.Query.tenantfilter -$Params = @{ - Identity = $request.query.guid -} - -try { - $state = if ($request.query.state -eq "enable") { $true } else { $false } - $Params = @{ Identity = $request.query.GUID; Enabled = $state } - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "Set-$($Request.query.Type)Connector" -cmdParams $params -UseSystemMailbox $true - $Result = "Set transport rule $($Request.query.guid) to $($request.query.State)" - Write-LogMessage -API "TransportRules" -tenant $tenantfilter -message "Set Connector $($Request.query.guid) to $($request.query.State)" -sev Debug -} -catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception - $Result = $ErrorMessage -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{Results = $Result } - }) + $Params = @{ + Identity = $request.query.guid + } + try { + $state = if ($request.query.state -eq 'enable') { $true } else { $false } + $Params = @{ Identity = $request.query.GUID; Enabled = $state } + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "Set-$($Request.query.Type)Connector" -cmdParams $params -UseSystemMailbox $true + $Result = "Set Connector $($Request.query.guid) to $($request.query.State)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Set Connector $($Request.query.guid) to $($request.query.State)" -sev 'Info' + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Failed setting Connector $($Request.query.guid) to $($request.query.State). Error:$($_.Exception.Message)" -Sev 'Error' + $ErrorMessage = Get-NormalizedError -Message $_.Exception + $Result = $ErrorMessage } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{Results = $Result } + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditGroup.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditGroup.ps1 index 7cce727e5294..3a15a163aaa7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditGroup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditGroup.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-EditGroup { +Function Invoke-EditGroup { <# .FUNCTIONALITY Entrypoint @@ -8,180 +8,180 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -$Results = [System.Collections.ArrayList]@() + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Results = [System.Collections.ArrayList]@() + $userobj = $Request.body -$userobj = $Request.body + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' -# Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." - -$AddMembers = ($userobj.Addmember).value -if ($AddMembers) { - $AddMembers | ForEach-Object { - try { - $member = $_ - if ($member -like '*#EXT#*') { $member = [System.Web.HttpUtility]::UrlEncode($member) } - $MemberIDs = "https://graph.microsoft.com/v1.0/directoryObjects/" + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($member)" -tenantid $Userobj.tenantid).id - $addmemberbody = "{ `"members@odata.bind`": $(ConvertTo-Json @($MemberIDs)) }" - if ($userobj.groupType -eq "Distribution list" -or $userobj.groupType -eq "Mail-Enabled Security") { - $Params = @{ Identity = $userobj.groupid; Member = $member; BypassSecurityGroupManagerCheck = $true } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Add-DistributionGroupMember" -cmdParams $params -UseSystemMailbox $true - } - else { - New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)" -tenantid $Userobj.tenantid -type patch -body $addmemberbody -Verbose - } - Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Added $member to $($userobj.groupName) group" -Sev "Info" - $body = $results.add("Success. $member has been added") - } - catch { - $body = $results.add("Failed to add member $member to $($userobj.groupName): $($_.Exception.Message)") - } - } - -} -$AddContacts = ($userobj.AddContacts).value - -if ($AddContacts) { - $AddContacts | ForEach-Object { - try { - $member = $_ - if ($userobj.groupType -eq "Distribution list" -or $userobj.groupType -eq "Mail-Enabled Security") { - $Params = @{ Identity = $userobj.groupid; Member = $member; BypassSecurityGroupManagerCheck = $true } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Add-DistributionGroupMember" -cmdParams $params -UseSystemMailbox $true - Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Added $member to $($userobj.groupName) group" -Sev "Info" + $AddMembers = ($userobj.Addmember).value + if ($AddMembers) { + $AddMembers | ForEach-Object { + try { + $member = $_ + if ($member -like '*#EXT#*') { $member = [System.Web.HttpUtility]::UrlEncode($member) } + $MemberIDs = 'https://graph.microsoft.com/v1.0/directoryObjects/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($member)" -tenantid $Userobj.tenantid).id + $addmemberbody = "{ `"members@odata.bind`": $(ConvertTo-Json @($MemberIDs)) }" + if ($userobj.groupType -eq 'Distribution list' -or $userobj.groupType -eq 'Mail-Enabled Security') { + $Params = @{ Identity = $userobj.groupid; Member = $member; BypassSecurityGroupManagerCheck = $true } + New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true + } + else { + New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)" -tenantid $Userobj.tenantid -type patch -body $addmemberbody -Verbose + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Added $member to $($userobj.groupName) group" -Sev 'Info' $body = $results.add("Success. $member has been added") } - else { - Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "You cannot add a contact to a security group" -Sev "Error" - $body = $results.add("You cannot add a contact to a security group") + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to add member $member to $($userobj.groupName). Error:$($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Failed to add member $member to $($userobj.groupName): $($_.Exception.Message)") } } - catch { - $body = $results.add("Failed to add member $member to $($userobj.groupName): $($_.Exception.Message)") - } - } - -} -$RemoveMembers = ($userobj.Removemember).value -try { - if ($RemoveMembers) { - $RemoveMembers | ForEach-Object { - $member = $_ - if ($userobj.groupType -eq "Distribution list" -or $userobj.groupType -eq "Mail-Enabled Security") { - $Params = @{ Identity = $userobj.groupid; Member = $member ; BypassSecurityGroupManagerCheck = $true } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Remove-DistributionGroupMember" -cmdParams $params -UseSystemMailbox $true - } - else { - $MemberInfo = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid) - New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/members/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE - } - Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Removed $member from $($userobj.groupName) group" -Sev "Info" - $body = $results.add("Success. Member $member has been removed") - } } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Add member API failed. $($_.Exception.Message)" -Sev "Error" - $body = $results.add("Could not remove $RemoveMembers from $($userobj.groupName). $($_.Exception.Message)") -} + $AddContacts = ($userobj.AddContacts).value -$AddOwners = $userobj.Addowner.value -try { - if ($AddOwners) { - $AddOwners | ForEach-Object { + if ($AddContacts) { + $AddContacts | ForEach-Object { try { - $ID = "https://graph.microsoft.com/beta/users/" + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid).id - Write-Host $ID - $AddOwner = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/owners/`$ref" -tenantid $Userobj.tenantid -type POST -body ('{"@odata.id": "' + $ID + '"}') - Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Added owner $_ to $($userobj.groupName) group" -Sev "Info" - $body = $results.add("Success. $_ has been added") + $member = $_ + if ($userobj.groupType -eq 'Distribution list' -or $userobj.groupType -eq 'Mail-Enabled Security') { + $Params = @{ Identity = $userobj.groupid; Member = $member; BypassSecurityGroupManagerCheck = $true } + New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true + Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Added $member to $($userobj.groupName) group" -Sev 'Info' + $body = $results.add("Success. $member has been added") + } + else { + Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message 'You cannot add a contact to a security group' -Sev 'Error' + $body = $results.add('You cannot add a contact to a security group') + } } catch { - $body = $results.add("Failed to add owner $_ to $($userobj.groupName): $($_.Exception.Message)") + $body = $results.add("Failed to add member $member to $($userobj.groupName): $($_.Exception.Message)") } } } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -message "Add member API failed. $($_.Exception.Message)" -Sev "Error" -} + $RemoveMembers = ($userobj.Removemember).value + try { + if ($RemoveMembers) { + $RemoveMembers | ForEach-Object { + $member = $_ + if ($userobj.groupType -eq 'Distribution list' -or $userobj.groupType -eq 'Mail-Enabled Security') { + $Params = @{ Identity = $userobj.groupid; Member = $member ; BypassSecurityGroupManagerCheck = $true } + New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Remove-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true + } + else { + $MemberInfo = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid) + New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/members/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE + } + Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Removed $member from $($userobj.groupName) group" -Sev 'Info' + $body = $results.add("Success. Member $member has been removed") + } + } + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to remove $RemoveMembers from $($userobj.groupName). Error:$($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Could not remove $RemoveMembers from $($userobj.groupName). $($_.Exception.Message)") + } -$RemoveOwners = ($userobj.RemoveOwner).value -try { - if ($RemoveOwners) { - $RemoveOwners | ForEach-Object { - try { - $MemberInfo = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid) - New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/owners/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE - Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Removed $($MemberInfo.UserPrincipalname) from $($userobj.displayname) group" -Sev "Info" - $body = $results.add("Success. Member $_ has been removed from $($userobj.groupName)") - } - catch { - $body = $results.add("Failed to remove $_ from $($userobj.groupName): $($_.Exception.Message)") + $AddOwners = $userobj.Addowner.value + try { + if ($AddOwners) { + $AddOwners | ForEach-Object { + try { + $ID = 'https://graph.microsoft.com/beta/users/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid).id + Write-Host $ID + $AddOwner = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/owners/`$ref" -tenantid $Userobj.tenantid -type POST -body ('{"@odata.id": "' + $ID + '"}') + Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Added owner $_ to $($userobj.groupName) group" -Sev 'Info' + $body = $results.add("Success. $_ has been added") + } + catch { + $body = $results.add("Failed to add owner $_ to $($userobj.groupName): Error:$($_.Exception.Message)") + } } - } + + } + + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -tenant $Userobj.tenantid -API $APINAME -message "Add member API failed. $($_.Exception.Message)" -Sev 'Error' } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Add member API failed. $($_.Exception.Message)" -Sev "Error" - $body = $results.add("Could not remove $RemoveMembers from $($userobj.groupName). $($_.Exception.Message)") -} -if ($userobj.allowExternal -eq 'true') { + $RemoveOwners = ($userobj.RemoveOwner).value try { - if ($userobj.groupType -eq "Distribution list") { - $Params = @{ Identity = $userobj.groupid; RequireSenderAuthenticationEnabled = $false } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Set-DistributionGroup" -cmdParams $params - } - else { - $Params = @{ Identity = $userobj.groupid; RequireSenderAuthenticationEnabled = $false } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Set-UnifiedGroup" -cmdParams $params + if ($RemoveOwners) { + $RemoveOwners | ForEach-Object { + try { + $MemberInfo = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid) + New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/owners/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE + Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Removed $($MemberInfo.UserPrincipalname) from $($userobj.displayname) group" -Sev 'Info' + $body = $results.add("Success. Member $_ has been removed from $($userobj.groupName)") + } + catch { + $body = $results.add("Failed to remove $_ from $($userobj.groupName): $($_.Exception.Message)") + } + } } - $body = $results.add("Allowed external senders to send to $($userobj.groupName).") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Allowed external senders to send to $($userobj.groupName)" -Sev "Error" - } catch { - $body = $results.add("Failed to allow external senders to send to $($userobj.groupName).") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to allow external senders for $($userobj.groupName). $($_.Exception.Message)" -Sev "Error" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to remove $RemoveMembers from $($userobj.groupName). Error:$($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Could not remove $RemoveMembers from $($userobj.groupName). $($_.Exception.Message)") } -} + if ($userobj.allowExternal -eq 'true') { + try { + if ($userobj.groupType -eq 'Distribution list') { + $Params = @{ Identity = $userobj.groupid; RequireSenderAuthenticationEnabled = $false } + New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Set-DistributionGroup' -cmdParams $params + } + else { + $Params = @{ Identity = $userobj.groupid; RequireSenderAuthenticationEnabled = $false } + New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Set-UnifiedGroup' -cmdParams $params + } + $body = $results.add("Allowed external senders to send to $($userobj.groupName).") + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Allowed external senders to send to $($userobj.groupName)" -Sev 'Info' -if ($userobj.sendCopies -eq 'true') { - try { - $Params = @{ Identity = $userobj.Groupid; subscriptionEnabled = $true; AutoSubscribeNewMembers = $true } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Set-UnifiedGroup" -cmdParams $params -useSystemMailbox $true + } + catch { + $body = $results.add("Failed to allow external senders to send to $($userobj.groupName).") + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to allow external senders for $($userobj.groupName). Error:$($_.Exception.Message)" -Sev 'Error' + } + + } + + if ($userobj.sendCopies -eq 'true') { + try { + $Params = @{ Identity = $userobj.Groupid; subscriptionEnabled = $true; AutoSubscribeNewMembers = $true } + New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Set-UnifiedGroup' -cmdParams $params -useSystemMailbox $true - $MemberParams = @{ Identity = $userobj.Groupid; LinkType = "members" } - $Members = New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Get-UnifiedGrouplinks" -cmdParams $MemberParams + $MemberParams = @{ Identity = $userobj.Groupid; LinkType = 'members' } + $Members = New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Get-UnifiedGrouplinks' -cmdParams $MemberParams - $MemberSmtpAddresses = $Members | ForEach-Object { $_.PrimarySmtpAddress } + $MemberSmtpAddresses = $Members | ForEach-Object { $_.PrimarySmtpAddress } - $subscriberParams = @{ Identity = $userobj.Groupid; LinkType = "subscribers"; Links = @($MemberSmtpAddresses) } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet "Add-UnifiedGrouplinks" -cmdParams $subscriberParams -Anchor $userobj.mail + $subscriberParams = @{ Identity = $userobj.Groupid; LinkType = 'subscribers'; Links = @($MemberSmtpAddresses) } + New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Add-UnifiedGrouplinks' -cmdParams $subscriberParams -Anchor $userobj.mail - $body = $results.add("Send Copies of team emails and events to team members inboxes for $($userobj.mail) enabled.") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Send Copies of team emails and events to team members inboxes for $($userobj.mail) enabled." -Sev "Error" - } - catch { - $body = $results.add("Failed to Send Copies of team emails and events to team members inboxes for $($userobj.mail).") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to Send Copies of team emails and events to team members inboxes for $($userobj.mail). $($_.Exception.Message)" -Sev "Error" + $body = $results.add("Send Copies of team emails and events to team members inboxes for $($userobj.mail) enabled.") + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Send Copies of team emails and events to team members inboxes for $($userobj.mail) enabled." -Sev 'Info' + } + catch { + $body = $results.add("Failed to Send Copies of team emails and events to team members inboxes for $($userobj.mail).") + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to Send Copies of team emails and events to team members inboxes for $($userobj.mail). Error:$($_.Exception.Message)" -Sev 'Error' + } } -} -$body = @{"Results" = @($results) } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) + $body = @{'Results' = @($results) } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditPolicy.ps1 index 076ecde86889..e30d3971cb00 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditPolicy.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-EditPolicy { +Function Invoke-EditPolicy { <# .FUNCTIONALITY Entrypoint @@ -8,38 +8,38 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$user = $request.headers.'x-ms-client-principal' -$Tenant = $request.body.tenantid -$ID = $request.body.groupid -$displayname = $request.body.Displayname -$description = $request.body.Description -$AssignTo = if ($request.body.Assignto -ne "on") { $request.body.Assignto } -$results = try { - $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' - $Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations('$ID')" -tenantid $tenant -type PATCH -body $CreateBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Edited policy $($Displayname)" -Sev "Error" - if ($AssignTo) { - $AssignBody = if ($AssignTo -ne "AllDevicesAndUsers") { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations('$($ID)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $AssignTo" -Sev "Info" + $Tenant = $request.body.tenantid + $ID = $request.body.groupid + $displayname = $request.body.Displayname + $description = $request.body.Description + $AssignTo = if ($request.body.Assignto -ne 'on') { $request.body.Assignto } + + $results = try { + $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' + $Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations('$ID')" -tenantid $tenant -type PATCH -body $CreateBody + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Edited policy $($Displayname)" -Sev 'Info' + if ($AssignTo) { + $AssignBody = if ($AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations('$($ID)')/assign" -tenantid $tenant -type POST -body $AssignBody + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $AssignTo" -Sev 'Info' + } + "Successfully edited policy for $($Tenant)" + } + catch { + "Failed to add policy for $($Tenant): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed editing policy $($Displayname). Error:$($_.Exception.Message)" -Sev 'Error' + continue } - "Successfully edited policy for $($Tenant)" -} -catch { - "Failed to add policy for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed editing policy $($Displayname). Error: $($_.Exception.Message)" -Sev "Error" - continue -} -$body = [pscustomobject]@{"Results" = $results } + $body = [pscustomobject]@{'Results' = $results } -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditSpamFilter.ps1 index 7138186ae76b..9f98d280f511 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditSpamFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditSpamFilter.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-EditSpamFilter { +Function Invoke-EditSpamFilter { <# .FUNCTIONALITY Entrypoint @@ -8,29 +8,29 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -$Tenantfilter = $request.Query.tenantfilter + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Tenantfilter = $request.Query.tenantfilter + $Params = @{ + Identity = $request.query.name + } -$Params = @{ - Identity = $request.query.name -} + try { + $cmdlet = if ($request.query.state -eq 'enable') { 'Enable-HostedContentFilterRule' } else { 'Disable-HostedContentFilterRule' } + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params + $Result = "Set Spamfilter rule to $($request.query.State)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Set Spamfilter rule $($Request.query.name) to $($request.query.State)" -sev Info + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Failed setting Spamfilter rule $($Request.query.guid) to $($request.query.State). Error:$($_.Exception.Message)" -Sev 'Error' + $ErrorMessage = Get-NormalizedError -Message $_.Exception + $Result = $ErrorMessage + } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{Results = $Result } + }) -try { - $cmdlet = if ($request.query.state -eq "enable") { "Enable-HostedContentFilterRule" } else { "Disable-HostedContentFilterRule" } - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params - $Result = "Set Spamfilter rule to $($request.query.State)" - Write-LogMessage -API "TransportRules" -tenant $tenantfilter -message "Set transport rule $($Request.query.name) to $($request.query.State)" -sev Debug } -catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception - $Result = $ErrorMessage -} -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{Results = $Result } - }) - - } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTenant.ps1 index 0c10dc387b08..77db47a5ff51 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTenant.ps1 @@ -20,9 +20,10 @@ Function Invoke-EditTenant { $AADGraphtoken = (Get-GraphToken -scope 'https://graph.windows.net/.default') $allTenantsDetails = (Invoke-RestMethod -Method GET -Uri 'https://graph.windows.net/myorganization/contracts?api-version=1.6' -ContentType 'application/json' -Headers $AADGraphtoken) $tenantObjectId = $allTenantsDetails.value | Where-Object { $_.customerContextId -eq $customerContextId } | Select-Object 'objectId' - } catch { - $Results = "Failed to retrieve list of tenants. Error: $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantDisplayName) -message "Failed to retrieve list of tenants. Error: $($_.Exception.Message)" -Sev 'Error' + } + catch { + $Results = "Failed to retrieve list of tenants. Error: $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantDisplayName) -message "Failed to retrieve list of tenants. Error:$($_.Exception.Message)" -Sev 'Error' } @@ -36,16 +37,19 @@ Function Invoke-EditTenant { $Tenant = Get-CIPPAzDataTableEntity @TenantsTable -Filter $Filter $Tenant.displayName = $tenantDisplayName Update-AzDataTableEntity @TenantsTable -Entity $Tenant - } catch { + } + catch { $AddedText = 'but could not edit the tenant cache. Clear the tenant cache to display the updated details' } Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantDisplayName -message "Edited tenant $tenantDisplayName" -Sev 'Info' $results = "Successfully amended details for $($Tenant.displayName) $AddedText" - } catch { + } + catch { $results = "Failed to amend details for $tenantDisplayName : $($_.Exception.Message)" - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantDisplayName -message "Failed amending details $tenantDisplayName. Error: $($_.Exception.Message)" -Sev 'Error' + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantDisplayName -message "Failed amending details $tenantDisplayName. Error:$($_.Exception.Message)" -Sev 'Error' } - } else { + } + else { $Results = 'Could not find the tenant to edit in the contract endpoint. Please ensure you have a reseller relationship with the tenant you are trying to edit.' } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTransportRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTransportRule.ps1 index 11c669a95358..20f93fd4014f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTransportRule.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditTransportRule.ps1 @@ -21,8 +21,10 @@ Function Invoke-EditTransportRule { $cmdlet = if ($request.query.state -eq 'enable') { 'Enable-TransportRule' } else { 'Disable-TransportRule' } $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -UseSystemMailbox $true $Result = "Set transport rule $($Request.query.guid) to $($request.query.State)" - Write-LogMessage -API 'TransportRules' -tenant $tenantfilter -message "Set transport rule $($Request.query.guid) to $($request.query.State)" -sev Debug - } catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Set transport rule $($Request.query.guid) to $($request.query.State)" -sev Info + } + catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Failed setting transport rule $($Request.query.guid) to $($request.query.State). Error:$($_.Exception.Message)" -Sev 'Error' $ErrorMessage = Get-NormalizedError -Message $_.Exception $Result = $ErrorMessage } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditUser.ps1 index 996352c449dd..132ccd3af8af 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-EditUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-EditUser.ps1 @@ -10,6 +10,7 @@ Function Invoke-EditUser { $APIName = $TriggerMetadata.FunctionName Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $userobj = $Request.body $Results = [System.Collections.ArrayList]@() $licenses = ($userobj | Select-Object 'License_*').psobject.properties.value @@ -54,7 +55,8 @@ Function Invoke-EditUser { $results.add("Success. The password has been set to $($userobj.password)") Write-LogMessage -API $APINAME -tenant ($UserObj.tenantid) -user $request.headers.'x-ms-client-principal' -message "Reset $($userobj.displayname)'s Password" -Sev 'Info' } - } catch { + } + catch { Write-LogMessage -API $APINAME -tenant ($UserObj.tenantid) -user $request.headers.'x-ms-client-principal' -message "User edit API failed. $($_.Exception.Message)" -Sev 'Error' $results.add( "Failed to edit user. $($_.Exception.Message)") } @@ -68,7 +70,7 @@ Function Invoke-EditUser { $CurrentLicenses = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($userobj.Userid)" -tenantid $Userobj.tenantid $RemovalList = ($CurrentLicenses.assignedLicenses | Where-Object -Property skuid -NotIn $licenses).skuid $LicensesToRemove = if ($RemovalList) { ConvertTo-Json @( $RemovalList ) } else { '[]' } - + $liclist = foreach ($license in $Licenses) { '{"disabledPlans": [],"skuId": "' + $license + '" },' } $LicenseBody = '{"addLicenses": [' + $LicList + '], "removeLicenses": ' + $LicensesToRemove + '}' if ($userobj.RemoveAllLicenses) { $LicenseBody = '{"addLicenses": [], "removeLicenses": ' + $LicensesToRemove + '}' } @@ -79,7 +81,8 @@ Function Invoke-EditUser { $results.add( 'Success. User license has been edited.' ) } - } catch { + } + catch { Write-LogMessage -API $APINAME -tenant ($UserObj.tenantid) -user $request.headers.'x-ms-client-principal' -message "License assign API failed. $($_.Exception.Message)" -Sev 'Error' $results.add( "We've failed to assign the license. $($_.Exception.Message)") } @@ -95,7 +98,8 @@ Function Invoke-EditUser { $results.add( 'Success. added aliasses to user.') } - } catch { + } + catch { Write-LogMessage -API $APINAME -tenant ($UserObj.tenantid) -user $request.headers.'x-ms-client-principal' -message "Alias API failed. $($_.Exception.Message)" -Sev 'Error' $results.add( "Successfully edited user. The password is $password. We've failed to create the Aliases: $($_.Exception.Message)") } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 index d027158c7be7..cb68a725d7e3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 @@ -16,16 +16,14 @@ function Invoke-ExecAddMultiTenantApp { $ExistingApp = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/applications(appId='$($Request.body.AppId)')" -tenantid $ENV:tenantid -NoAuthCheck $true $DelegateResourceAccess = $Existingapp.requiredResourceAccess $ApplicationResourceAccess = $Existingapp.requiredResourceAccess - } - catch { + } catch { 'Failed to get existing permissions. The app does not exist in the partner tenant.' } } #This needs to be moved to a queue. if ('allTenants' -in $Request.body.SelectedTenants.defaultDomainName) { $TenantFilter = (Get-Tenants).defaultDomainName - } - else { + } else { $TenantFilter = $Request.body.SelectedTenants.defaultDomainName } @@ -39,14 +37,12 @@ function Invoke-ExecAddMultiTenantApp { delegateResourceAccess = $DelegateResourceAccess }) "Queued application to tenant $Tenant. See the logbook for deployment details" - } - catch { + } catch { "Error queuing application to tenant $Tenant - $($_.Exception.Message)" } } $StatusCode = [HttpStatusCode]::OK - } - catch { + } catch { $ErrorMsg = Get-NormalizedError -message $($_.Exception.Message) $Results = "Function Error: $ErrorMsg" $StatusCode = [HttpStatusCode]::BadRequest diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAssignPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAssignPolicy.ps1 new file mode 100644 index 000000000000..ae866ed3f485 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAssignPolicy.ps1 @@ -0,0 +1,39 @@ +using namespace System.Net + +Function Invoke-ExecAssignPolicy { + <# + .FUNCTIONALITY + Entrypoint + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + $Tenant = $request.query.tenantfilter + $ID = $request.query.id + $displayname = $request.query.Displayname + $AssignTo = if ($request.query.Assignto -ne 'on') { $request.query.Assignto } + + $results = try { + if ($AssignTo) { + $assign = Set-CIPPAssignedPolicy -PolicyId $ID -TenantFilter $tenant -GroupName $AssignTo -Type $Request.query.Type + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $AssignTo" -Sev 'Info' + } + "Successfully edited policy for $($Tenant)" + } catch { + "Failed to add policy for $($Tenant): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed editing policy $($Displayname). Error:$($_.Exception.Message)" -Sev 'Error' + continue + } + + $body = [pscustomobject]@{'Results' = $results } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionSync.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionSync.ps1 index 38f050341aed..effb15af199d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionSync.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionSync.ps1 @@ -41,25 +41,29 @@ Function Invoke-ExecExtensionSync { $Filter = "PartitionKey eq 'NinjaOrgsMapping'" $TenantsToProcess = Get-AzDataTableEntity @CIPPMapping -Filter $Filter | Where-Object { $Null -ne $_.NinjaOne -and $_.NinjaOne -ne '' } - foreach ($Tenant in $TenantsToProcess) { + if ($Request.Query.TenantID) { + $Tenant = $TenantsToProcess | Where-Object {$_.RowKey -eq $Request.Query.TenantID} + if (($Tenant | Measure-Object).count -eq 1){ + Push-OutputBinding -Name NinjaProcess -Value @{ + 'NinjaAction' = 'SyncTenant' + 'MappedTenant' = $Tenant + } + $Results = [pscustomobject]@{'Results' = "NinjaOne Synchronization Queued for $($Tenant.NinjaOneName)" } + } else { + $Results = [pscustomobject]@{'Results' = "Tenant was not found." } + } + + } else { + Push-OutputBinding -Name NinjaProcess -Value @{ - 'NinjaAction' = 'SyncTenant' - 'MappedTenant' = $Tenant + 'NinjaAction' = 'SyncTenants' } - } + $Results = [pscustomobject]@{'Results' = "NinjaOne Synchronization Queuing $(($TenantsToProcess | Measure-Object).count) Tenants" } - $AddObject = @{ - PartitionKey = 'NinjaConfig' - RowKey = 'NinjaLastRunTime' - 'SettingValue' = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') } - Add-AzDataTableEntity @Table -Entity $AddObject -Force - - Write-LogMessage -API 'NinjaOneAutoMap_Queue' -user 'CIPP' -message "NinjaOne Synchronization Queued for $(($TenantsToProcess | Measure-Object).count) Tenants" -Sev 'Info' - - $Results = [pscustomobject]@{'Results' = "NinjaOne Synchronization Queued for $(($TenantsToProcess | Measure-Object).count) Tenants" } + } catch { $Results = [pscustomobject]@{'Results' = "Could not start NinjaOne Sync: $($_.Exception.Message)" } Write-LogMessage -API 'Scheduler_Billing' -tenant 'none' -message "Could not start NinjaOne Sync $($_.Exception.Message)" -sev Error diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionsConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionsConfig.ps1 index fd9725fe5ff9..772e36bfac74 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionsConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionsConfig.ps1 @@ -23,7 +23,7 @@ $results = try { # Check if NinjaOne URL is set correctly and the intance has at least version 5.6 if ($request.body.NinjaOne) { try { - [version]$Version = (Invoke-WebRequest -Method GET -Uri "https://$($request.body.NinjaOne.Instance -replace '/ws','')/app-version.txt" -ea stop).content + [version]$Version = (Invoke-WebRequest -Method GET -Uri "https://$(($request.body.NinjaOne.Instance -replace '/ws','') -replace 'https://','')/app-version.txt" -ea stop).content } catch { throw "Failed to connect to NinjaOne check your Instance is set correctly eg 'app.ninjarmmm.com'" } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecGDAPInvite.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecGDAPInvite.ps1 index 050a162ebd6f..8eb97c978ce5 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecGDAPInvite.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecGDAPInvite.ps1 @@ -1,6 +1,5 @@ - using namespace System.Net - - Function Invoke-ExecGDAPInvite { +using namespace System.Net +Function Invoke-ExecGDAPInvite { <# .FUNCTIONALITY Entrypoint @@ -8,78 +7,74 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$RoleMappings = $Request.body.gdapRoles -$Results = [System.Collections.Generic.List[string]]::new() -$InviteUrls = [System.Collections.Generic.List[string]]::new() + $RoleMappings = $Request.body.gdapRoles + $Results = [System.Collections.Generic.List[string]]::new() + if ($RoleMappings.roleDefinitionId -contains '62e90394-69f5-4237-9190-012177145e10') { + $AutoExtendDuration = 'PT0S' + } else { + $AutoExtendDuration = 'P180D' + } -if ($RoleMappings.roleDefinitionId -contains '62e90394-69f5-4237-9190-012177145e10') { - $AutoExtendDuration = 'PT0S' -} else { - $AutoExtendDuration = 'P180D' -} + $Table = Get-CIPPTable -TableName 'GDAPInvites' + try { + $JSONBody = @{ + 'displayName' = "$((New-Guid).GUID)" + 'accessDetails' = @{ + 'unifiedRoles' = @($RoleMappings | Select-Object roleDefinitionId) + } + 'autoExtendDuration' = $AutoExtendDuration + 'duration' = 'P730D' + } | ConvertTo-Json -Depth 5 -Compress -$Table = Get-CIPPTable -TableName 'GDAPInvites' -try { - $JSONBody = @{ - 'displayName' = "$((New-Guid).GUID)" - 'accessDetails' = @{ - 'unifiedRoles' = @($RoleMappings | Select-Object roleDefinitionId) - } - 'autoExtendDuration' = $AutoExtendDuration - 'duration' = 'P730D' - } | ConvertTo-Json -Depth 5 -Compress + $NewRelationship = New-GraphPostRequest -NoAuthCheck $True -uri 'https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships' -type POST -body $JSONBody -verbose -tenantid $env:TenantID + Start-Sleep -Milliseconds 100 + $Count = 0 + do { + $CheckActive = New-GraphGetRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($NewRelationship.id)" -tenantid $env:TenantID + Start-Sleep -Milliseconds 200 + $Count++ + } until ($CheckActive.status -eq 'created' -or $Count -gt 5) - $NewRelationship = New-GraphPostRequest -NoAuthCheck $True -uri 'https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships' -type POST -body $JSONBody -verbose -tenantid $env:TenantID - Start-Sleep -Milliseconds 100 - $Count = 0 - do { - $CheckActive = New-GraphGetRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($NewRelationship.id)" -tenantid $env:TenantID - Start-Sleep -Milliseconds 200 - $Count++ - } until ($CheckActive.status -eq 'created' -or $Count -gt 5) + if ($CheckActive.status -eq 'created') { + # Lock for approval + $JSONBody = @{ + 'action' = 'lockForApproval' + } | ConvertTo-Json + $NewRelationshipRequest = New-GraphPostRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($NewRelationship.id)/requests" -type POST -body $JSONBody -verbose -tenantid $env:TenantID - if ($CheckActive.status -eq 'created') { - # Lock for approval - $JSONBody = @{ - 'action' = 'lockForApproval' - } | ConvertTo-Json - $NewRelationshipRequest = New-GraphPostRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($NewRelationship.id)/requests" -type POST -body $JSONBody -verbose -tenantid $env:TenantID + if ($NewRelationshipRequest.action -eq 'lockForApproval') { + $InviteUrl = "https://admin.microsoft.com/AdminPortal/Home#/partners/invitation/granularAdminRelationships/$($NewRelationship.id)" - if ($NewRelationshipRequest.action -eq 'lockForApproval') { - $InviteUrl = "https://admin.microsoft.com/AdminPortal/Home#/partners/invitation/granularAdminRelationships/$($NewRelationship.id)" - $InviteUrls.Add($InviteUrl) + $InviteEntity = [PSCustomObject]@{ + 'PartitionKey' = 'invite' + 'RowKey' = $NewRelationship.id + 'InviteUrl' = $InviteUrl + 'RoleMappings' = [string](@($RoleMappings) | ConvertTo-Json -Depth 10 -Compress) + } + Add-CIPPAzDataTableEntity @Table -Entity $InviteEntity - $InviteEntity = [PSCustomObject]@{ - 'PartitionKey' = 'invite' - 'RowKey' = $NewRelationship.id - 'InviteUrl' = $InviteUrl - 'RoleMappings' = [string](@($RoleMappings) | ConvertTo-Json -Depth 10) + $Results.add('GDAP relationship invite created. Copy the URL below and log in as a Global Admin for the new tenant to approve the invite.') + } else { + $Results.add('Error creating GDAP relationship request') } - Add-CIPPAzDataTableEntity @Table -Entity $InviteEntity - - $Results.add("Relationship created - Invite URL: $InviteUrl") - } else { - $Results.add('Error creating GDAP relationship request') } + } catch { + $Results.add('Error creating GDAP relationship') + Write-Host "GDAP ERROR: $($_.Exception.Message)" } -} catch { - $Results.add('Error creating GDAP relationship') - Write-Host "GDAP ERROR: $($_.Exception.Message)" -} -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created GDAP Invite - $InviteUrl" -Sev 'Info' - -$body = @{ - Results = @($Results) - InviteUrls = @($InviteUrls) -} -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created GDAP Invite - $InviteUrl" -Sev 'Info' + $body = @{ + Results = @($Results) + Invite = $InviteEntity } + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecOnboardTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecOnboardTenant.ps1 new file mode 100644 index 000000000000..c67be5c4de8f --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecOnboardTenant.ps1 @@ -0,0 +1,87 @@ +using namespace System.Net + +function Invoke-ExecOnboardTenant { + param($Request, $TriggerMetadata) + + $APIName = 'ExecOnboardTenant' + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + $Id = $Request.Body.Id + if ($Id) { + try { + $OnboardTable = Get-CIPPTable -TableName 'TenantOnboarding' + $TenantOnboarding = Get-CIPPAzDataTableEntity @OnboardTable -Filter "RowKey eq '$Id'" + + if (!$TenantOnboarding -or [bool]$Request.Query.Retry) { + $OnboardingSteps = [PSCustomObject]@{ + 'Step1' = @{ + 'Status' = 'pending' + 'Title' = 'Step 1: GDAP Invite' + 'Message' = 'Waiting for onboarding job to start' + } + 'Step2' = @{ + 'Status' = 'pending' + 'Title' = 'Step 2: GDAP Role Test' + 'Message' = 'Waiting for Step 1' + } + 'Step3' = @{ + 'Status' = 'pending' + 'Title' = 'Step 3: GDAP Group Mapping' + 'Message' = 'Waiting for Step 2' + } + 'Step4' = @{ + 'Status' = 'pending' + 'Title' = 'Step 4: CPV Refresh' + 'Message' = 'Waiting for Step 3' + } + 'Step5' = @{ + 'Status' = 'pending' + 'Title' = 'Step 5: Graph API Test' + 'Message' = 'Waiting for Step 4' + } + } + $TenantOnboarding = [PSCustomObject]@{ + PartitionKey = 'Onboarding' + RowKey = [string]$Id + CustomerId = '' + Status = 'queued' + OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) + Relationship = '' + Logs = '' + Exception = '' + } + Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop + + Push-OutputBinding -Name QueueItem -Value ([pscustomobject]@{ + FunctionName = 'ExecOnboardTenantQueue' + id = $Id + Roles = $Request.Body.gdapRoles + }) + } + + $Steps = $TenantOnboarding.OnboardingSteps | ConvertFrom-Json + $OnboardingSteps = foreach ($Step in $Steps.PSObject.Properties.Name) { $Steps.$Step } + $Relationship = try { $TenantOnboarding.Relationship | ConvertFrom-Json -ErrorAction Stop } catch { @{} } + $Logs = try { $TenantOnboarding.Logs | ConvertFrom-Json -ErrorAction Stop } catch { @{} } + $TenantOnboarding.OnboardingSteps = $OnboardingSteps + $TenantOnboarding.Relationship = $Relationship + $TenantOnboarding.Logs = $Logs + $Results = $TenantOnboarding + + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMsg = Get-NormalizedError -message $($_.Exception.Message) + $Results = "Function Error: $($_.InvocationInfo.ScriptLineNumber) - $ErrorMsg" + $StatusCode = [HttpStatusCode]::BadRequest + } + } else { + $StatusCode = [HttpStatusCode]::NotFound + $Results = 'Relationship not found' + } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = $Results + }) + +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSAMSetup.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSAMSetup.ps1 index 1319ced9aa86..a224182bf1c9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSAMSetup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSAMSetup.ps1 @@ -180,7 +180,7 @@ Function Invoke-ExecSAMSetup { Remove-AzDataTableEntity @Table -Entity $Rows $step = 5 - $Results = @{'message' = 'Installation completed.'; step = $step + $Results = @{'message' = 'setup completed.'; step = $step } } } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecStandardsRun.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecStandardsRun.ps1 new file mode 100644 index 000000000000..c205bf24d57b --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecStandardsRun.ps1 @@ -0,0 +1,28 @@ +using namespace System.Net + +Function Invoke-ExecStandardsRun { + <# + .FUNCTIONALITY + Entrypoint + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $tenantfilter = if ($Request.Query.TenantFilter) { $Request.Query.TenantFilter } else { 'allTenants' } + try { + $null = Invoke-CIPPStandardsRun -Tenantfilter $tenantfilter + $Results = "Successfully Started Standards Run for Tenant $tenantfilter" + } catch { + $Results = "Failed to start standards run for $tenantfilter. Error: $($_.Exception.Message)" + } + + $Results = [pscustomobject]@{'Results' = "$results" } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Results + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBPA.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBPA.ps1 index eea73a9c4b9e..e9f9f9a1fbf4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBPA.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBPA.ps1 @@ -62,7 +62,7 @@ Function Invoke-ListBPA { } $Results = [PSCustomObject]@{ - Data = $Data + Data = @($Data) Columns = $Columns Style = $Style } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 index 13395bcac219..9460428ac793 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 @@ -25,17 +25,16 @@ function Invoke-ListFunctionParameters { if ($Function) { $CommandQuery.Name = $Function } - + $IgnoreList = 'entryPoint', 'internal' $CommonParameters = @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction', 'ErrorVariable', 'WarningVariable', 'InformationVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable', 'TenantFilter', 'APIName', 'ExecutingUser') - #temporary until I clean up the coremodule and move things private. - $TemporaryBlacklist = 'Get-CIPPAuthentication', 'Invoke-CippWebhookProcessing', 'Invoke-ListFunctionParameters', 'New-CIPPAPIConfig', 'New-CIPPGraphSubscription.ps1' + $TemporaryBlacklist = 'Get-CIPPAuthentication', 'Invoke-CippWebhookProcessing', 'Invoke-ListFunctionParameters', 'New-CIPPAPIConfig', 'New-CIPPGraphSubscription' try { $Functions = Get-Command @CommandQuery | Where-Object { $_.Visibility -eq 'Public' } $Results = foreach ($Function in $Functions) { if ($Function -In $TemporaryBlacklist) { continue } $Help = Get-Help $Function $ParamsHelp = ($Help | Select-Object -ExpandProperty parameters).parameter | Select-Object name, @{n = 'description'; exp = { $_.description.Text } } - if ($Help.Functionality -eq 'Entrypoint') { continue } + if ($Help.Functionality -in $IgnoreList) { continue } $Parameters = foreach ($Key in $Function.Parameters.Keys) { if ($CommonParameters -notcontains $Key) { $Param = $Function.Parameters.$Key diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGDAPInvite.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGDAPInvite.ps1 index 3ae888f60ec8..afc2bacfc630 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGDAPInvite.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGDAPInvite.ps1 @@ -15,18 +15,15 @@ Function Invoke-ListGDAPInvite { # Write to the Azure Functions log stream. Write-Host 'PowerShell HTTP trigger function processed a request.' - Write-Host ($Request | ConvertTo-Json) + $Table = Get-CIPPTable -TableName 'GDAPInvites' if (![string]::IsNullOrEmpty($Request.Query.RelationshipId)) { - $Table = Get-CIPPTable -TableName 'GDAPInvites' $Invite = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($Request.Query.RelationshipId)'" - Write-Host $Invite } else { - $Invite = @{} + $Invite = Get-CIPPAzDataTableEntity @Table } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $Invite }) - } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices copy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices copy.ps1 new file mode 100644 index 000000000000..8199d4204326 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices copy.ps1 @@ -0,0 +1,55 @@ +using namespace System.Net + +Function Invoke-ListMailboxMobileDevices { + <# + .FUNCTIONALITY + Entrypoint + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.TenantFilter + $Mailbox = $Request.Query.Mailbox + + Write-Host $TenantFilter + Write-Host $Mailbox + + $Bytes = [System.Text.Encoding]::UTF8.GetBytes($Mailbox) + $base64IdentityParam = [Convert]::ToBase64String($Bytes) + + try { + $GraphRequest = New-GraphGetRequest -uri "https://outlook.office365.com:443/adminapi/beta/$($TenantFilter)/mailbox('$($base64IdentityParam)')/MobileDevice/Exchange.GetMobileDeviceStatistics()/?IsEncoded=True" -Tenantid $tenantfilter -scope ExchangeOnline | Select-Object @{ Name = 'clientType'; Expression = { $_.ClientType } }, + @{ Name = 'clientVersion'; Expression = { $_.ClientVersion } }, + @{ Name = 'deviceAccessState'; Expression = { $_.DeviceAccessState } }, + @{ Name = 'deviceFriendlyName'; Expression = { if ([string]::IsNullOrEmpty($_.DeviceFriendlyName)) { 'Unknown' }else { $_.DeviceFriendlyName } } }, + @{ Name = 'deviceModel'; Expression = { $_.DeviceModel } }, + @{ Name = 'deviceOS'; Expression = { $_.DeviceOS } }, + @{ Name = 'deviceType'; Expression = { $_.DeviceType } }, + @{ Name = 'firstSync'; Expression = { $_.FirstSyncTime.toString() } }, + @{ Name = 'lastSyncAttempt'; Expression = { $_.LastSyncAttemptTime.toString() } }, + @{ Name = 'lastSuccessSync'; Expression = { $_.LastSuccessSync.toString() } }, + @{ Name = 'status'; Expression = { $_.Status } }, + @{ Name = 'deviceID'; Expression = { $_.deviceID } }, + @{ Name = 'Guid'; Expression = { $_.Guid } } + + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + $StatusCode = [HttpStatusCode]::Forbidden + $GraphRequest = $ErrorMessage + } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @($GraphRequest) + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRecipients.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRecipients.ps1 new file mode 100644 index 000000000000..29bc8bd8a01a --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRecipients.ps1 @@ -0,0 +1,45 @@ +using namespace System.Net + +Function Invoke-ListRecipients { + <# + .FUNCTIONALITY + Entrypoint + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.TenantFilter + try { + $Select = 'id,DisplayName,ExchangeGuid,ArchiveGuid,PrimarySmtpAddress,PrimarySMTPAddress,RecipientType,RecipientTypeDetails,EmailAddresses' + $ExoRequest = @{ + tenantid = $TenantFilter + cmdlet = 'Get-Recipient' + cmdParams = @{resultsize = 'unlimited' } + Select = $select + } + + $GraphRequest = (New-ExoRequest @ExoRequest) | Select-Object id, ExchangeGuid, ArchiveGuid, + @{ Name = 'UPN'; Expression = { $_.'PrimarySmtpAddress' } }, + @{ Name = 'mail'; Expression = { $_.'PrimarySmtpAddress' } }, + @{ Name = 'displayName'; Expression = { $_.'DisplayName' } } + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + $StatusCode = [HttpStatusCode]::Forbidden + $GraphRequest = $ErrorMessage + } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @($GraphRequest) + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 index f40095596f18..683f05eed5a1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 @@ -20,21 +20,24 @@ Function Invoke-ListSharedMailboxAccountEnabled { # Get Shared Mailbox Stuff try { $SharedMailboxList = (New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($TenantFilter)/Mailbox?`$filter=RecipientTypeDetails eq 'SharedMailbox'" -Tenantid $TenantFilter -scope ExchangeOnline) - $AllUsersAccountState = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?select=userPrincipalName,accountEnabled,displayName,givenName,surname' -tenantid $Tenantfilter + $AllUsersAccountState = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?select=id,userPrincipalName,accountEnabled,displayName,givenName,surname,onPremisesSyncEnabled' -tenantid $Tenantfilter $EnabledUsersWithSharedMailbox = foreach ($SharedMailbox in $SharedMailboxList) { # Match the User - $User = $AllUsersAccountState | Where-Object { $_.userPrincipalName -eq $SharedMailbox.userPrincipalName } | Select-Object -Property userPrincipalName, accountEnabled, displayName, givenName, surname -First 1 + $User = $AllUsersAccountState | Where-Object { $_.userPrincipalName -eq $SharedMailbox.userPrincipalName } | Select-Object -Property id, userPrincipalName, accountEnabled, displayName, givenName, surname, onPremisesSyncEnabled -First 1 if ($User.accountEnabled) { $User | Select-Object ` @{Name = 'UserPrincipalName'; Expression = { $User.UserPrincipalName } }, ` @{Name = 'displayName'; Expression = { $User.displayName } }, @{Name = 'givenName'; Expression = { $User.givenName } }, @{Name = 'surname'; Expression = { $User.surname } }, - @{Name = 'accountEnabled'; Expression = { $User.accountEnabled } } + @{Name = 'accountEnabled'; Expression = { $User.accountEnabled } }, + @{Name = 'id'; Expression = { $User.id } }, + @{Name = 'onPremisesSyncEnabled'; Expression = { $User.onPremisesSyncEnabled } } } } - } catch { + } + catch { Write-LogMessage -API 'Tenant' -tenant $tenantfilter -message "Shared Mailbox Enabled Accounts on $($tenantfilter). Error: $($_.exception.message)" -sev 'Error' } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 index 6efbb47e7e96..b1a7dc2236ab 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 @@ -1,6 +1,6 @@ - using namespace System.Net +using namespace System.Net - Function Invoke-ListSharepointQuota { +Function Invoke-ListSharepointQuota { <# .FUNCTIONALITY Entrypoint @@ -8,43 +8,47 @@ [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -# Write to the Azure Functions log stream. -Write-Host 'PowerShell HTTP trigger function processed a request' + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request' -# Interact with query parameters or the body of the request. -$TenantFilter = $Request.Query.TenantFilter + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.TenantFilter -if ($Request.Query.TenantFilter -eq 'AllTenants') { - $UsedStoragePercentage = 'Not Supported' -} else { - $tenantName = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $TenantFilter | Where-Object { $_.isInitial -eq $true }).id.Split('.')[0] + if ($Request.Query.TenantFilter -eq 'AllTenants') { + $UsedStoragePercentage = 'Not Supported' + } else { + try { + $tenantName = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $TenantFilter | Where-Object { $_.isInitial -eq $true }).id.Split('.')[0] - $sharepointToken = (Get-GraphToken -scope "https://$($tenantName)-admin.sharepoint.com/.default" -tenantid $TenantFilter) - $sharepointToken.Add('accept', 'application/json') - # Implement a try catch later to deal with sharepoint guest user settings - $sharepointQuota = (Invoke-RestMethod -Method 'GET' -Headers $sharepointToken -Uri "https://$($tenantName)-admin.sharepoint.com/_api/StorageQuotas()?api-version=1.3.2" -ErrorAction Stop).value | Sort-Object -Property GeoUsedStorageMB -Descending | Select-Object -First 1 + $sharepointToken = (Get-GraphToken -scope "https://$($tenantName)-admin.sharepoint.com/.default" -tenantid $TenantFilter) + $sharepointToken.Add('accept', 'application/json') + # Implement a try catch later to deal with sharepoint guest user settings + $sharepointQuota = (Invoke-RestMethod -Method 'GET' -Headers $sharepointToken -Uri "https://$($tenantName)-admin.sharepoint.com/_api/StorageQuotas()?api-version=1.3.2" -ErrorAction Stop).value | Sort-Object -Property GeoUsedStorageMB -Descending | Select-Object -First 1 - if ($sharepointQuota) { - $UsedStoragePercentage = [int](($sharepointQuota.GeoUsedStorageMB / $sharepointQuota.TenantStorageMB) * 100) + if ($sharepointQuota) { + $UsedStoragePercentage = [int](($sharepointQuota.GeoUsedStorageMB / $sharepointQuota.TenantStorageMB) * 100) + } + } catch { + $UsedStoragePercentage = 'Not available' + } } -} -$sharepointQuotaDetails = @{ - GeoUsedStorageMB = $sharepointQuota.GeoUsedStorageMB - TenantStorageMB = $sharepointQuota.TenantStorageMB - Percentage = $UsedStoragePercentage - Dashboard = "$($UsedStoragePercentage) / 100" -} + $sharepointQuotaDetails = @{ + GeoUsedStorageMB = $sharepointQuota.GeoUsedStorageMB + TenantStorageMB = $sharepointQuota.TenantStorageMB + Percentage = $UsedStoragePercentage + Dashboard = "$($UsedStoragePercentage) / 100" + } -$StatusCode = [HttpStatusCode]::OK + $StatusCode = [HttpStatusCode]::OK -# Associate values to output bindings by calling 'Push-OutputBinding'. -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = $sharepointQuotaDetails - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = $sharepointQuotaDetails + }) - } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserCounts.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserCounts.ps1 index f94a0a79027c..137a9c8cc902 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserCounts.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserCounts.ps1 @@ -23,10 +23,10 @@ Function Invoke-ListUserCounts { $GAs = 'Not Supported' $Guests = 'Not Supported' } else { - $Users = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1" -CountOnly -ComplexFilter -tenantid $TenantFilter - $LicUsers = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=assignedLicenses/`$count ne 0" -CountOnly -ComplexFilter -tenantid $TenantFilter - $GAs = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directoryRoles/roleTemplateId=62e90394-69f5-4237-9190-012177145e10/members?`$count=true" -CountOnly -ComplexFilter -tenantid $TenantFilter - $guests = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=userType eq 'Guest'" -CountOnly -ComplexFilter -tenantid $TenantFilter + try { $Users = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Users = 'Not available' } + try { $LicUsers = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=assignedLicenses/`$count ne 0" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Licusers = 'Not available' } + try { $GAs = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directoryRoles/roleTemplateId=62e90394-69f5-4237-9190-012177145e10/members?`$count=true" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Gas = 'Not available' } + try { $guests = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=userType eq 'Guest'" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Guests = 'Not available' } } $StatusCode = [HttpStatusCode]::OK $Counts = @{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserMailboxDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserMailboxDetails.ps1 index e59ecf17a22a..6a043ace73b2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserMailboxDetails.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListUserMailboxDetails.ps1 @@ -31,12 +31,18 @@ Function Invoke-ListUserMailboxDetails { } $MailboxDetailedRequest = New-ExoRequest -TenantID $TenantFilter -cmdlet 'Get-Mailbox' -cmdParams $FetchParam try { - $Archive = New-ExoRequest -TenantID $TenantFilter -cmdlet 'Get-Mailbox' -cmdParams $FetchParam - if ($Archive.ArchiveStatus -eq 'Active') { + if ($MailboxDetailedRequest.ArchiveStatus -eq 'Active') { $ArchiveEnabled = $True } else { $ArchiveEnabled = $False } + # Get organization config of auto expanding archive if it's disabled on user level + if (!$MailboxDetailedRequest.AutoExpandingArchiveEnabled -and $ArchiveEnabled) { + $OrgConfig = New-ExoRequest -TenantID $TenantFilter -cmdlet 'Get-OrganizationConfig' + $AutoExpandingArchiveEnabled = $OrgConfig.AutoExpandingArchiveEnabled + } else { + $AutoExpandingArchiveEnabled = $MailboxDetailedRequest.AutoExpandingArchiveEnabled + } $FetchParam = @{ Identity = $MailRequest.PrimarySmtpAddress @@ -116,7 +122,7 @@ Function Invoke-ListUserMailboxDetails { TotalArchiveItemCount = [math]::Round($ArchiveSize.ItemCount, 2) BlockedForSpam = $BlockedForSpam ArchiveMailBox = $ArchiveEnabled - AutoExpandingArchive = $Archive.AutoExpandingArchiveEnabled + AutoExpandingArchive = $AutoExpandingArchiveEnabled RecipientTypeDetails = $MailboxDetailedRequest.RecipientTypeDetails } } else { @@ -140,7 +146,7 @@ Function Invoke-ListUserMailboxDetails { TotalArchiveItemCount = 0 BlockedForSpam = $BlockedForSpam ArchiveMailBox = $ArchiveEnabled - AutoExpandingArchive = $Archive.AutoExpandingArchiveEnabled + AutoExpandingArchive = $AutoExpandingArchiveEnabled RecipientTypeDetails = $MailboxDetailedRequest.RecipientTypeDetails } } diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-CIPPStandard.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-CIPPStandard.ps1 new file mode 100644 index 000000000000..03848da177c9 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Push-CIPPStandard.ps1 @@ -0,0 +1,12 @@ +function Push-CIPPStandard { + param ( + $QueueItem, $TriggerMetadata + ) + + Write-Host "Received queue item for $($QueueItem.Tenant) and standard $($QueueItem.Standard)." + $Tenant = $QueueItem.Tenant + $Standard = $QueueItem.Standard + $FunctionName = 'Invoke-CIPPStandard{0}' -f $Standard + Write-Host "We'll be running $FunctionName" + & $FunctionName -Tenant $Tenant -Settings $QueueItem.Settings +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 index b3ccd8a704ee..4c10f456584e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 @@ -4,16 +4,13 @@ function Push-ExecAddMultiTenantApp($QueueItem, $TriggerMetadata) { $ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Queueitem.Tenant if ($Queueitem.AppId -Notin $ServicePrincipalList.appId) { $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $queueitem.tenant -body "{ `"appId`": `"$($Queueitem.appId)`" }" - Write-LogMessage -message "Added $($Queueitem.AppId) to tenant $($Queueitem.Tenant)" -tenant $Queueitem.Tenant -API "Add Multitenant App" -sev Info + Write-LogMessage -message "Added $($Queueitem.AppId) to tenant $($Queueitem.Tenant)" -tenant $Queueitem.Tenant -API 'Add Multitenant App' -sev Info + } else { + Write-LogMessage -message "This app already exists in tenant $($Queueitem.Tenant). We're adding the required permissions." -tenant $Queueitem.Tenant -API 'Add Multitenant App' -sev Info } - else { - Write-LogMessage -message "This app already exists in tenant $($Queueitem.Tenant). We're adding the required permissions." -tenant $Queueitem.Tenant -API "Add Multitenant App" -sev Info - } - - Add-CIPPApplicationPermission -RequiredResourceAccess $queueitem.applicationResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant - Add-CIPPDelegatedPermission -RequiredResourceAccess $queueitem.DelegateResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant - } - catch { - Write-LogMessage -message "Error adding application to tenant $($Queueitem.Tenant) - $($_.Exception.Message)" -tenant $Queueitem.Tenant -API "Add Multitenant App" -sev Error + Add-CIPPApplicationPermission -RequiredResourceAccess [pscustomobject]$queueitem.applicationResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant + Add-CIPPDelegatedPermission -RequiredResourceAccess [pscustomobject]$queueitem.DelegateResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant + } catch { + Write-LogMessage -message "Error adding application to tenant $($Queueitem.Tenant) - $($_.Exception.Message)" -tenant $Queueitem.Tenant -API 'Add Multitenant App' -sev Error } } \ No newline at end of file diff --git a/Modules/CIPPCore/Public/GraphHelper/Convert-SKUName.ps1 b/Modules/CIPPCore/Public/GraphHelper/Convert-SKUName.ps1 index 2bd91fcf7a19..7d0d5e874aea 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Convert-SKUName.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Convert-SKUName.ps1 @@ -1,4 +1,8 @@ function Convert-SKUname($skuname, $skuID) { + <# + .FUNCTIONALITY + Internal + #> $ConvertTable = Import-Csv Conversiontable.csv if ($skuname) { $ReturnedName = ($ConvertTable | Where-Object { $_.String_Id -eq $skuname } | Select-Object -Last 1).'Product_Display_Name' } if ($skuID) { $ReturnedName = ($ConvertTable | Where-Object { $_.guid -eq $skuid } | Select-Object -Last 1).'Product_Display_Name' } diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-AuthorisedRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-AuthorisedRequest.ps1 index 89f8684d2e8e..f8891f84899d 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-AuthorisedRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-AuthorisedRequest.ps1 @@ -1,5 +1,9 @@ function Get-AuthorisedRequest { + <# + .FUNCTIONALITY + Internal + #> [CmdletBinding()] Param( [string]$TenantID, diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-CIPPTable.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-CIPPTable.ps1 index 99567e300e18..b050af128cee 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-CIPPTable.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-CIPPTable.ps1 @@ -1,4 +1,8 @@ function Get-CIPPTable { + <# + .FUNCTIONALITY + Internal + #> [CmdletBinding()] param ( $tablename = 'CippLogs' diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 index 6568e28b867a..f887e8ce850e 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 @@ -1,4 +1,8 @@ function Get-ClassicAPIToken($tenantID, $Resource) { + <# + .FUNCTIONALITY + Internal + #> $TokenKey = '{0}-{1}' -f $TenantID, $Resource if ($script:classictoken.$TokenKey -and [int](Get-Date -UFormat %s -Millisecond 0) -lt $script:classictoken.$TokenKey.expires_on) { Write-Host 'Classic: cached token' diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-GraphBulkResultByID.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-GraphBulkResultByID.ps1 index e71d8c8ffb25..ed8d6de49833 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-GraphBulkResultByID.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-GraphBulkResultByID.ps1 @@ -1,4 +1,8 @@ function Get-GraphBulkResultByID ($Results, $ID, [switch]$Value) { + <# + .FUNCTIONALITY + Internal + #> if ($Value) { ($Results | Where-Object { $_.id -eq $ID }).body.value } else { diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-GraphToken.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-GraphToken.ps1 index 8a654c8e979a..05b1b7f9c8fc 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-GraphToken.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-GraphToken.ps1 @@ -1,4 +1,8 @@ function Get-GraphToken($tenantid, $scope, $AsApp, $AppID, $refreshToken, $ReturnRefresh, $SkipCache) { + <# + .FUNCTIONALITY + Internal + #> if (!$scope) { $scope = 'https://graph.microsoft.com/.default' } if (!$env:SetFromProfile) { $CIPPAuth = Get-CIPPAuthentication; Write-Host 'Could not get Refreshtoken from environment variable. Reloading token.' } $AuthBody = @{ diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 index 96d5b0b4533c..98ce8bdbf8dc 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 @@ -1,4 +1,8 @@ function Get-NormalizedError { + <# + .FUNCTIONALITY + Internal + #> [CmdletBinding()] param ( [string]$message diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 index 4f0c1a16cbf8..e44eccbea5d9 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 @@ -1,4 +1,8 @@ function Get-Tenants { + <# + .FUNCTIONALITY + Internal + #> param ( [Parameter( ParameterSetName = 'Skip', Mandatory = $True )] [switch]$SkipList, diff --git a/Modules/CIPPCore/Public/GraphHelper/New-ClassicAPIGetRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-ClassicAPIGetRequest.ps1 index 1528e0e4393d..d97dfc3bb99f 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-ClassicAPIGetRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-ClassicAPIGetRequest.ps1 @@ -1,6 +1,9 @@ function New-ClassicAPIGetRequest($TenantID, $Uri, $Method = 'GET', $Resource = 'https://admin.microsoft.com', $ContentType = 'application/json') { - + <# + .FUNCTIONALITY + Internal + #> if ((Get-AuthorisedRequest -Uri $uri -TenantID $tenantid)) { $token = Get-ClassicAPIToken -Tenant $tenantID -Resource $Resource diff --git a/Modules/CIPPCore/Public/GraphHelper/New-DeviceLogin.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-DeviceLogin.ps1 index 1d80e47ba069..2046e3fa158b 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-DeviceLogin.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-DeviceLogin.ps1 @@ -1,4 +1,8 @@ function New-DeviceLogin { + <# + .FUNCTIONALITY + Internal + #> [CmdletBinding()] param ( [string]$clientid, diff --git a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 index d5df999e6a03..cfe78a4af8c6 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 @@ -1,5 +1,8 @@ function New-ExoRequest ($tenantid, $cmdlet, $cmdParams, $useSystemMailbox, $Anchor, $NoAuthCheck, $Select) { - + <# + .FUNCTIONALITY + Internal + #> if ((Get-AuthorisedRequest -TenantID $tenantid) -or $NoAuthCheck -eq $True) { $token = Get-ClassicAPIToken -resource 'https://outlook.office365.com' -Tenantid $tenantid $tenant = (get-tenants -IncludeErrors | Where-Object { $_.defaultDomainName -eq $tenantid -or $_.customerId -eq $tenantid }).customerId diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 index d328a7518865..ebe6af9675b9 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 @@ -1,4 +1,8 @@ function New-GraphBulkRequest { + <# + .FUNCTIONALITY + Internal + #> Param( $tenantid, $NoAuthCheck, diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 index 731c09da25b0..bc0ef417a3c3 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 @@ -1,4 +1,8 @@ function New-GraphGetRequest { + <# + .FUNCTIONALITY + Internal + #> Param( $uri, $tenantid, diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 index a133d7a93f7d..9b4848253d98 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 @@ -1,5 +1,9 @@ function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $NoAuthCheck, $skipTokenCache, $AddedHeaders) { + <# + .FUNCTIONALITY + Internal + #> if ($NoAuthCheck -or (Get-AuthorisedRequest -Uri $uri -TenantID $tenantid)) { $headers = Get-GraphToken -tenantid $tenantid -scope $scope -AsApp $asapp -SkipCache $skipTokenCache if ($AddedHeaders) { diff --git a/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 index 7ac373da6ffb..91dd8ce4a74b 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 @@ -1,4 +1,8 @@ function New-TeamsAPIGetRequest($Uri, $tenantID, $Method = 'GET', $Resource = '48ac35b8-9aa8-4d74-927d-1f4a14a0b239', $ContentType = 'application/json') { + <# + .FUNCTIONALITY + Internal + #> if ((Get-AuthorisedRequest -Uri $uri -TenantID $tenantid)) { $token = Get-ClassicAPIToken -Tenant $tenantid -Resource $Resource diff --git a/Modules/CIPPCore/Public/GraphHelper/New-passwordString.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-passwordString.ps1 index 4e6e27befdc8..6793c5cc17b3 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-passwordString.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-passwordString.ps1 @@ -1,4 +1,8 @@ function New-passwordString { + <# + .FUNCTIONALITY + Internal + #> [CmdletBinding()] param ( [int]$count = 12 diff --git a/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 b/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 index b789fe87e298..1fa4b612af40 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 @@ -1,14 +1,7 @@ function Read-JwtAccessDetails { <# - .SYNOPSIS - Parse Microsoft JWT access tokens - - .DESCRIPTION - Extract JWT access token details for verification - - .PARAMETER Token - Token to get details for - + .FUNCTIONALITY + Internal #> [cmdletbinding()] param( diff --git a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 index b2da4587453c..1bbab4a3f025 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 @@ -1,4 +1,8 @@ function Remove-CIPPCache { + <# + .FUNCTIONALITY + Internal + #> param ( $TenantsOnly ) diff --git a/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1 b/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1 index 2c5ea7d00ba7..fbef7fae41bf 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1 @@ -1,4 +1,8 @@ function Write-LogMessage ($message, $tenant = 'None', $API = 'None', $tenantId = $null, $user, $sev) { + <# + .FUNCTIONALITY + Internal + #> try { $username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($user)) | ConvertFrom-Json).userDetails } catch { diff --git a/Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookRenewal.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookRenewal.ps1 index ab2686655b39..e26271907be0 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookRenewal.ps1 +++ b/Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookRenewal.ps1 @@ -11,13 +11,35 @@ function Invoke-CippGraphWebhookRenewal { foreach ($UpdateSub in $WebhookData) { try { $TenantFilter = $UpdateSub.PartitionKey - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/subscriptions/$($UpdateSub.SubscriptionID)" -tenantid $TenantFilter -type PATCH -body $body -Verbose - $UpdateSub.Expiration = $RenewalDate - $null = Add-AzDataTableEntity @WebhookTable -Entity $UpdateSub -Force - Write-LogMessage -user 'CIPP' -API 'Renew_Graph_Subscriptions' -message "Renewed Subscription:$($UpdateSub.SubscriptionID)" -Sev "Info" -tenant $TenantFilter + try { + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/subscriptions/$($UpdateSub.SubscriptionID)" -tenantid $TenantFilter -type PATCH -body $body -Verbose + $UpdateSub.Expiration = $RenewalDate + $null = Add-AzDataTableEntity @WebhookTable -Entity $UpdateSub -Force + Write-LogMessage -user 'CIPP' -API 'Renew_Graph_Subscriptions' -message "Renewed Subscription:$($UpdateSub.SubscriptionID)" -Sev "Info" -tenant $TenantFilter + + } catch { + # Rebuild creation parameters + $BaseURL = "$(([uri]($UpdateSub.WebhookNotificationUrl)).Host)" + if ($UpdateSub.TypeofSubscription) { + $TypeofSubscription = "$($UpdateSub.TypeofSubscription)" + } else { + $TypeofSubscription = 'updated' + } + $Resource = "$($UpdateSub.Resource)" + $EventType = "$($UpdateSub.EventType)" + + Write-LogMessage -user 'CIPP' -API 'Renew_Graph_Subscriptions' -message "Recreating: $($UpdateSub.SubscriptionID) as renewal failed." -Sev "Info" -tenant $TenantFilter + $CreateResult = New-CIPPGraphSubscription -TenantFilter $TenantFilter -TypeofSubscription $TypeofSubscription -BaseURL $BaseURL -Resource $Resource -EventType $EventType -ExecutingUser 'GraphSubscriptionRenewal' -Recreate + + if ($CreateResult -match 'Created Webhook subscription for') { + Remove-AzDataTableEntity @WebhookTable -Entity $UpdateSub + } + + } + } catch { - Write-LogMessage -user 'CIPP' -API 'Renew_Graph_Subscriptions' -message "Failed to renew Webhook Subscription: $($UpdateSub.SubscriptionID)" -Sev "Error" -tenant $TenantFilter + Write-LogMessage -user 'CIPP' -API 'Renew_Graph_Subscriptions' -message "Failed to renew Webhook Subscription: $($UpdateSub.SubscriptionID). Linenumber: $($_.InvocationInfo.ScriptLineNumber) Error: $($_.Exception.message)" -Sev "Error" -tenant $TenantFilter } } } diff --git a/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 new file mode 100644 index 000000000000..353551cdaadf --- /dev/null +++ b/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 @@ -0,0 +1,90 @@ + +function Invoke-CIPPStandardsRun { + [CmdletBinding()] + param( + [Parameter(Mandatory = $false)] + [string]$TenantFilter = 'allTenants' + ) + Write-Host "Starting process for standards - $($tenantFilter)" + $Table = Get-CippTable -tablename 'standards' + $SkipList = Get-Tenants -SkipList + if ($tenantfilter -ne 'allTenants') { + $Filter = "PartitionKey eq 'standards' and RowKey eq '$($tenantfilter)'" + } else { + $Filter = "PartitionKey eq 'standards'" + } + $Tenants = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json + + #Migrate from old standards to new standards. + $Tenants | Where-Object -Property 'v2.1' -NE $null | ForEach-Object { + $OldStd = $_ + $OldStd.standards.psobject.properties.name | ForEach-Object { + if ($_ -eq 'MailContacts') { + $OldStd.Standards.$_ = [pscustomobject]@{ + GeneralContact = $OldStd.Standards.MailContacts.GeneralContact.Mail + SecurityContact = $OldStd.Standards.MailContacts.SecurityContact.Mail + MarketingContact = $OldStd.Standards.MailContacts.MarketingContact.Mail + TechContact = $OldStd.Standards.MailContacts.TechContact.Mail + remediate = $true + } + } else { + if ($OldStd.Standards.$_ -eq $true -and $_ -ne 'v2.1') { + $OldStd.Standards.$_ = @{ remediate = $true } + } else { + $OldStd.Standards.$_ | Add-Member -NotePropertyName 'remediate' -NotePropertyValue $true -Force + } + + } + } + $OldStd | Add-Member -NotePropertyName 'v2.1' -NotePropertyValue $true -PassThru -Force + $Entity = @{ + PartitionKey = 'standards' + RowKey = "$($OldStd.Tenant)" + JSON = "$($OldStd | ConvertTo-Json -Depth 10)" + } + Add-CIPPAzDataTableEntity @Table -Entity $Entity -Force + } + + #Execute standards + + $object = foreach ($Tenant in $Tenants) { + $Tenant.standards.psobject.properties.name | ForEach-Object { + $Standard = $_ + if ($Tenant.Tenant -ne 'AllTenants' -and $SkipList.defaultDomainName -notcontains $Tenant.Tenant) { + if ($Standard -ne 'OverrideAllTenants') { + [pscustomobject]@{ + Tenant = $tenant.Tenant + Standard = $Standard + Settings = $Tenant.standards.$Standard + } + } + } elseif ($Tenant.Tenant -eq 'AllTenants') { + Write-Host "Working on all Tenants Standard. Showing which tasks we'll run below this." + Get-Tenants | ForEach-Object { + $TenantForStandard = $_ + $TenantStandard = $Tenants | Where-Object { $_.Tenant -eq $TenantForStandard.defaultDomainName } + if ($TenantStandard.standards.OverrideAllTenants.remediate -ne $true) { + Write-Host "$($TenantForStandard.defaultDomainName) - $Standard" + [pscustomobject]@{ + Tenant = $_.defaultDomainName + Standard = $Standard + Settings = $Tenant.standards.$Standard + } + } + } + } + } + } + + #For each item in our object, run the queue. + + foreach ($task in $object | Where-Object -Property Standard -NotLike 'v2*') { + $QueueItem = [pscustomobject]@{ + Tenant = $task.Tenant + Standard = $task.Standard + Settings = $task.Settings + FunctionName = 'CIPPStandard' + } + Push-OutputBinding -Name QueueItem -Value $QueueItem + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1 index 09c474712e18..f16befc4906b 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1 @@ -11,19 +11,15 @@ Function Invoke-RemoveExConnector { $APIName = $TriggerMetadata.FunctionName Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $Tenantfilter = $request.Query.tenantfilter - - - $Params = @{ - Identity = $request.query.guid - } - + try { + $Params = @{ Identity = $request.query.GUID } - - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "Remove-$($Request.query.Type)Connector" -cmdParams $params + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "Remove-$($Request.query.Type)Connector" -cmdParams $params -useSystemMailbox $true $Result = "Deleted $($Request.query.guid)" Write-LogMessage -API 'TransportRules' -tenant $tenantfilter -message "Deleted transport rule $($Request.query.guid)" -sev Debug - } catch { + } + catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception $Result = $ErrorMessage } diff --git a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 b/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 index 18a58945002e..649a50c452df 100644 --- a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 @@ -10,7 +10,8 @@ function New-CIPPGraphSubscription { $Resource, $EventType, $APIName = "Create Webhook", - $ExecutingUser + $ExecutingUser, + [Switch]$Recreate ) $CIPPID = (New-Guid).GUID $WebhookTable = Get-CIPPTable -TableName webhookTable @@ -36,13 +37,14 @@ function New-CIPPGraphSubscription { } $null = Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow + Write-LogMessage -user $ExecutingUser -API $APIName -message "Created Webhook subscription for $($TenantFilter)" -Sev "Info" -tenant $TenantFilter } else { # First check if there is an exsiting Webhook in place $WebhookFilter = "PartitionKey eq '$($TenantFilter)'" $ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter $MatchedWebhook = $ExistingWebhooks | Where-Object { $_.Resource -eq $Resource } - if (($MatchedWebhook | Measure-Object).count -eq 0) { + if (($MatchedWebhook | Measure-Object).count -eq 0 -or $Recreate) { $expiredate = (Get-Date).AddDays(1).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ") $params = @{ @@ -64,14 +66,17 @@ function New-CIPPGraphSubscription { Resource = [string]$Resource Expiration = [string]$expiredate SubscriptionID = [string]$GraphRequest.id + TypeofSubscription = [string]$TypeofSubscription WebhookNotificationUrl = [string]$GraphRequest.notificationUrl } $null = Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow #todo: add remove webhook function, add check webhook function, add list webhooks function #add refresh webhook function based on table. + Write-LogMessage -user $ExecutingUser -API $APIName -message "Created Graph Webhook subscription for $($TenantFilter)" -Sev "Info" -tenant $TenantFilter + } else { + Write-LogMessage -user $ExecutingUser -API $APIName -message "Existing Graph Webhook subscription for $($TenantFilter) found" -Sev "Info" -tenant $TenantFilter } } - Write-LogMessage -user $ExecutingUser -API $APIName -message "Created Webhook subscription for $($TenantFilter)" -Sev "Info" -tenant $TenantFilter return "Created Webhook subscription for $($TenantFilter)" } catch { Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription: $($_.Exception.Message)" -Sev "Error" -tenant $TenantFilter diff --git a/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 b/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 index bc1234fd05e6..a43996e3fe68 100644 --- a/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 +++ b/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 @@ -15,7 +15,7 @@ function Revoke-CIPPSessions { } catch { - Write-LogMessage -user $ExecutingUser -API $APIName -message "Revoked sessions for $($username)" -Sev "Info" -tenant $TenantFilter + Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to revoke sessions for $($username): $($_.Exception.Message)" -Sev "Error" -tenant $TenantFilter return "Revoke Session Failed: $($_.Exception.Message)" } } diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 index 1303cd72a9bb..19e1f7975818 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 @@ -5,53 +5,49 @@ function Set-CIPPAssignedPolicy { $PolicyId, $Type, $TenantFilter, - $APIName = "Assign Application", + $APIName = 'Assign Policy', $ExecutingUser ) try { $assignmentsObject = switch ($GroupName) { - "allLicensedUsers" { + 'allLicensedUsers' { @( @{ - id = "" target = @{ - "@odata.type" = "#microsoft.graph.allLicensedUsersAssignmentTarget" + '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' } } ) break } - "AllDevices" { + 'AllDevices' { @( @{ - id = "" target = @{ - "@odata.type" = "#microsoft.graph.allDevicesAssignmentTarget" + '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' } } ) break } - "AllDevicesAndUsers" { + 'AllDevicesAndUsers' { @( @{ - id = "" target = @{ - "@odata.type" = "#microsoft.graph.allDevicesAssignmentTarget" + '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' } }, @{ - id = "" target = @{ - "@odata.type" = "#microsoft.graph.allLicensedUsersAssignmentTarget" + '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' } } ) } default { - $GroupNames = $GroupName.Split(",") - $GroupIds = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups" -tenantid $TenantFilter | ForEach-Object { + $GroupNames = $GroupName.Split(',') + $GroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $TenantFilter | ForEach-Object { $Group = $_ foreach ($SingleName in $GroupNames) { if ($_.displayname -like $SingleName) { @@ -62,7 +58,7 @@ function Set-CIPPAssignedPolicy { foreach ($Group in $GroupIds) { @{ target = @{ - "@odata.type" = "#microsoft.graph.groupAssignmentTarget" + '@odata.type' = '#microsoft.graph.groupAssignmentTarget' groupId = $Group } } @@ -72,12 +68,11 @@ function Set-CIPPAssignedPolicy { $assignmentsObject = [PSCustomObject]@{ assignments = @($assignmentsObject) } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$Type('$($PolicyId)')/assign" -tenantid $tenantFilter -type POST -body ($assignmentsObject | ConvertTo-Json -Depth 10) - Write-LogMessage -user $ExecutingUser -API $APIName -message "Assigned Policy to $($GroupName)" -Sev "Info" -tenant $TenantFilter + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$Type('$($PolicyId)')/assign" -tenantid $tenantFilter -type POST -body ($assignmentsObject | ConvertTo-Json -Depth 10) + Write-LogMessage -user $ExecutingUser -API $APIName -message "Assigned Policy to $($GroupName)" -Sev 'Info' -tenant $TenantFilter return "Assigned policy to $($GroupName)" - } - catch { - Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to assign Policy to $GroupName" -Sev "Error" -tenant $TenantFilter + } catch { + Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to assign Policy to $GroupName" -Sev 'Error' -tenant $TenantFilter return "Could not assign policy to $GroupName. Error: $($_.Exception.Message)" } } diff --git a/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 b/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 new file mode 100644 index 000000000000..f3c488a4e805 --- /dev/null +++ b/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 @@ -0,0 +1,56 @@ +function Set-CIPPDefaultAPDeploymentProfile { + [CmdletBinding()] + param( + $tenantFilter, + $displayname, + $description, + $devicenameTemplate, + $allowWhiteGlove, + $CollectHash, + $usertype, + $DeploymentMode, + $hideChangeAccount, + $assignTo, + $hidePrivacy, + $hideTerms, + $Autokeyboard, + $ExecutingUser, + $APIName = 'Add Default Enrollment Status Page' + ) + try { + $ObjBody = [pscustomobject]@{ + '@odata.type' = '#microsoft.graph.azureADWindowsAutopilotDeploymentProfile' + 'displayName' = "$($displayname)" + 'description' = "$($description)" + 'deviceNameTemplate' = "$($DeviceNameTemplate)" + 'language' = 'os-default' + 'enableWhiteGlove' = $([bool]($allowWhiteGlove)) + 'deviceType' = 'windowsPc' + 'extractHardwareHash' = $([bool]($CollectHash)) + 'roleScopeTagIds' = @() + 'hybridAzureADJoinSkipConnectivityCheck' = $false + 'outOfBoxExperienceSettings' = @{ + 'deviceUsageType' = "$DeploymentMode" + 'hideEscapeLink' = $([bool]($hideChangeAccount)) + 'hidePrivacySettings' = $([bool]($hidePrivacy)) + 'hideEULA' = $([bool]($hideTerms)) + 'userType' = "$usertype" + 'skipKeyboardSelectionPage' = $([bool]($Autokeyboard)) + } + } + $Body = ConvertTo-Json -InputObject $ObjBody + Write-Host $Body + $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeploymentProfiles' -body $body -tenantid $tenantfilter + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenantfilter) -message "Added Autopilot profile $($Displayname)" -Sev 'Info' + if ($AssignTo) { + $AssignBody = '{"target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}}' + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeploymentProfiles/$($GraphRequest.id)/assignments" -tenantid $tenantfilter -type POST -body $AssignBody + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenantfilter) -message "Assigned autopilot profile $($Displayname) to $AssignTo" -Sev 'Info' + } + "Successfully added profile for $($tenantfilter)" + } catch { + "Failed to add profile for $($tenantfilter): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($tenantfilter) -message "Failed adding Autopilot Profile $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + continue + } +} diff --git a/Modules/CIPPCore/Public/Set-CIPPDefaultAPEnrollment.ps1 b/Modules/CIPPCore/Public/Set-CIPPDefaultAPEnrollment.ps1 new file mode 100644 index 000000000000..3c3f21eeceab --- /dev/null +++ b/Modules/CIPPCore/Public/Set-CIPPDefaultAPEnrollment.ps1 @@ -0,0 +1,45 @@ +function Set-CIPPDefaultAPEnrollment { + [CmdletBinding()] + param( + $TenantFilter, + $ShowProgress, + $BlockDevice, + $AllowReset, + $EnableLog, + $ErrorMessage, + $TimeOutInMinutes, + $AllowFail, + $OBEEOnly, + $ExecutingUser, + $APIName = 'Add Default Enrollment Status Page' + ) + try { + $ObjBody = [pscustomobject]@{ + '@odata.type' = '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration' + 'id' = 'DefaultWindows10EnrollmentCompletionPageConfiguration' + 'displayName' = 'All users and all devices' + 'description' = 'This is the default enrollment status screen configuration applied with the lowest priority to all users and all devices regardless of group membership.' + 'showInstallationProgress' = [bool]$ShowProgress + 'blockDeviceSetupRetryByUser' = [bool]$blockDevice + 'allowDeviceResetOnInstallFailure' = [bool]$AllowReset + 'allowLogCollectionOnInstallFailure' = [bool]$EnableLog + 'customErrorMessage' = "$ErrorMessage" + 'installProgressTimeoutInMinutes' = $TimeOutInMinutes + 'allowDeviceUseOnInstallFailure' = [bool]$AllowFail + 'selectedMobileAppIds' = @() + 'trackInstallProgressForAutopilotOnly' = [bool]$OBEEOnly + 'disableUserStatusTrackingAfterFirstUser' = $true + 'roleScopeTagIds' = @() + } + $Body = ConvertTo-Json -InputObject $ObjBody + $ExistingStatusPage = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations' -tenantid $($TenantFilter)) | Where-Object { $_.id -like '*DefaultWindows10EnrollmentCompletionPageConfiguration' } + $GraphRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations/$($ExistingStatusPage.ID)" -body $body -Type PATCH -tenantid $($TenantFilter) + "Successfully changed default enrollment status page for $($($TenantFilter))" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($TenantFilter) -message "Added Autopilot Enrollment Status Page $($Displayname)" -Sev 'Info' + + } catch { + "Failed to change default enrollment status page for $($($TenantFilter)): $($_.Exception.Message)" + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($TenantFilter) -message "Failed adding Autopilot Enrollment Status Page $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + continue + } +} diff --git a/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 b/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 index 9db8ddd5002a..2b3361a6054d 100644 --- a/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 @@ -6,7 +6,7 @@ function Set-CIPPForwarding { $tenantFilter, $username, $ExecutingUser, - $APIName = "Forwarding", + $APIName = 'Forwarding', $Forward, $KeepCopy, $Disable @@ -14,13 +14,12 @@ function Set-CIPPForwarding { try { if (!$username) { $username = $userid } - $permissions = New-ExoRequest -tenantid $tenantFilter -cmdlet "Set-mailbox" -cmdParams @{Identity = $userid; ForwardingSMTPAddress = $forwardingSMTPAddress; ForwardingAddress = $Forward ; DeliverToMailboxAndForward = [bool]$KeepCopy } -Anchor $username + $permissions = New-ExoRequest -tenantid $tenantFilter -cmdlet 'Set-mailbox' -cmdParams @{Identity = $userid; ForwardingSMTPAddress = $forwardingSMTPAddress; ForwardingAddress = $Forward ; DeliverToMailboxAndForward = [bool]$KeepCopy } -Anchor $username if (!$Disable) { "Forwarding all email for $username to $Forward" } else { "Disabled forwarding for $username" } - Write-LogMessage -user $ExecutingUser -API $APIName -message "Set Forwarding for $($username) to $Forward" -Sev "Info" -tenant $TenantFilter - } - catch { - Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not add forwarding for $($username)" -Sev "Error" -tenant $TenantFilter + Write-LogMessage -user $ExecutingUser -API $APIName -message "Set Forwarding for $($username) to $Forward" -Sev 'Info' -tenant $TenantFilter + } catch { + Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not add forwarding for $($username)" -Sev 'Error' -tenant $TenantFilter return "Could not add forwarding for $($username). Error: $($_.Exception.Message)" } } diff --git a/Modules/CIPPCore/Public/Set-CIPPGDAPInviteGroups.ps1 b/Modules/CIPPCore/Public/Set-CIPPGDAPInviteGroups.ps1 index ca159b6611d5..407eccddc796 100644 --- a/Modules/CIPPCore/Public/Set-CIPPGDAPInviteGroups.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPGDAPInviteGroups.ps1 @@ -1,17 +1,45 @@ function Set-CIPPGDAPInviteGroups { - Param() + Param($Relationship) $Table = Get-CIPPTable -TableName 'GDAPInvites' - $InviteList = Get-CIPPAzDataTableEntity @Table - if (($InviteList | Measure-Object).Count -gt 0) { - #$LastDay = Get-Date (Get-Date).AddHours(-26) -UFormat '+%Y-%m-%dT%H:%M:%S.000Z' - #$NewActivations = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=((status eq 'active') and (activatedDateTime gt $LastDay))" - $Activations = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=status eq 'active'" + if ($Relationship) { + $Invite = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($Relationship.id)'" + $APINAME = 'GDAPInvites' + $RoleMappings = $Invite.RoleMappings | ConvertFrom-Json - foreach ($Activation in $Activations) { - if ($InviteList.RowKey -contains $Activation.id) { - Write-Host "Mapping groups for GDAP relationship: $($Activation.id)" - Push-OutputBinding -Name gdapinvitequeue -Value $Activation.id + foreach ($role in $RoleMappings) { + try { + $Mappingbody = ConvertTo-Json -Depth 10 -InputObject @{ + 'accessContainer' = @{ + 'accessContainerId' = "$($Role.GroupId)" + 'accessContainerType' = 'securityGroup' + } + 'accessDetails' = @{ + 'unifiedRoles' = @(@{ + 'roleDefinitionId' = "$($Role.roleDefinitionId)" + }) + } + } + New-GraphPostRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($Relationship.id)/accessAssignments" -tenantid $env:TenantID -type POST -body $MappingBody -verbose + Start-Sleep -Milliseconds 100 + } catch { + Write-LogMessage -API $APINAME -message "GDAP Group mapping failed for $($Relationship.customer.displayName) - Group: $($role.GroupId) - Exception: $($_.Exception.Message)" -Sev Error + return $false + } + } + Write-LogMessage -API $APINAME -message "Groups mapped for GDAP Relationship: $($Relationship.customer.displayName) - $($Relationship.customer.displayName)" -Sev Info + Remove-AzDataTableEntity @Table -Entity $Invite + return $true + } else { + $InviteList = Get-CIPPAzDataTableEntity @Table + if (($InviteList | Measure-Object).Count -gt 0) { + $Activations = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=status eq 'active'" + + foreach ($Activation in $Activations) { + if ($InviteList.RowKey -contains $Activation.id) { + Write-Host "Mapping groups for GDAP relationship: $($Activation.customer.displayName) - $($Activation.id)" + Push-OutputBinding -Name gdapinvitequeue -Value $Activation + } } } } diff --git a/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 b/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 index 8365e4b64a90..79b6222f5c37 100644 --- a/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 @@ -14,7 +14,7 @@ function Set-CIPPOutOfOffice { try { if (-not $StartTime) { - $StartTime = (Get-Date).ToString("yyyy-MM-dd HH:mm") + $StartTime = (Get-Date).ToString() } if (-not $EndTime) { $EndTime = (Get-Date $StartTime).AddDays(7) @@ -27,7 +27,7 @@ function Set-CIPPOutOfOffice { else { $OutOfOffice = New-ExoRequest -tenantid $TenantFilter -cmdlet "Set-MailboxAutoReplyConfiguration" -cmdParams @{Identity = $userid; AutoReplyState = $State; InternalMessage = $InternalMessage; ExternalMessage = $ExternalMessage; StartTime = $StartTime; EndTime = $EndTime } -Anchor $userid Write-LogMessage -user $ExecutingUser -API $APIName -message "Scheduled Out-of-office for $($userid) between $StartTime and $EndTime" -Sev "Info" -tenant $TenantFilter - return "Scheduled Out-of-office for $($userid) between $StartTime and $EndTime" + return "Scheduled Out-of-office for $($userid) between $($StartTime.toString()) and $($EndTime.toString())" } } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 new file mode 100644 index 000000000000..652c5611b5f8 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 @@ -0,0 +1,21 @@ +function Invoke-CIPPStandardAPConfig { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + + $APINAME = 'Standards' + try { + Write-Host $($settings | ConvertTo-Json -Depth 100) + if ($settings.NotLocalAdmin -eq $true) { $usertype = 'Standard' } else { $usertype = 'Administrator' } + $DeploymentMode = if ($settings.DeploymentMode -eq 'true') { 'shared' } else { 'singleUser' } + Set-CIPPDefaultAPDeploymentProfile -tenantFilter $tenant -displayname $settings.DisplayName -description $settings.Description -usertype $usertype -DeploymentMode $DeploymentMode -assignto $settings.AssignTo -devicenameTemplate $Settings.DeviceNameTemplate -allowWhiteGlove $Settings.allowWhiteGlove -CollectHash $Settings.CollectHash -hideChangeAccount $Settings.HideChangeAccount -hidePrivacy $Settings.HidePrivacy -hideTerms $Settings.HideTerms -Autokeyboard $Settings.Autokeyboard + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create Default Autopilot config: $($_.exception.message)" -sev 'Error' + } + + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 new file mode 100644 index 000000000000..8eba3f5ffa1d --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 @@ -0,0 +1,17 @@ +function Invoke-CIPPStandardAPESP { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + $APINAME = 'Standards' + try { + Set-CIPPDefaultAPEnrollment -TenantFilter $Tenant -ShowProgress $Settings.ShowProgress -BlockDevice $Settings.blockDevice -AllowReset $Settings.AllowReset -EnableLog $Settings.EnableLog -ErrorMessage $Settings.ErrorMessage -TimeOutInMinutes $Settings.TimeOutInMinutes -AllowFail $Settings.AllowFail -OBEEOnly $Settings.OBEEOnly + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create default Autopilot Enrollment: $($_.exception.message)" -sev 'Error' + } + } + + +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 new file mode 100644 index 000000000000..e61c9bd9e75e --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 @@ -0,0 +1,41 @@ +function Invoke-CIPPStandardActivityBasedTimeout { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $State = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -tenantid $tenant).id + + If ($Settings.remediate) { + try { + if (!$State) { + $body = @' +{ + "displayName": "DefaultTimeoutPolicy", + "isOrganizationDefault": true, + "definition":["{\"ActivityBasedTimeoutPolicy\":{\"Version\":1,\"ApplicationPolicies\":[{\"ApplicationId\":\"default\",\"WebSessionIdleTimeout\":\"01:00:00\"}]}}"] +} +'@ + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -Type POST -Body $body -ContentType 'application/json') + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled Activity Based Timeout of one hour' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Activity Based Timeout $($_.exception.message)" -sev Error + } + } + + if ($Settings.alert) { + + if ($State) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Activity Based Timeout is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Activity Based Timeout is not enabled' -sev Alert + } + } + + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'ActivityBasedTimeout' -FieldValue [bool]$state -StoreAs bool -Tenant $tenant + } + +} + diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 new file mode 100644 index 000000000000..ecf181d8497a --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardAddDKIM { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $DKIM = (New-ExoRequest -tenantid $tenant -cmdlet 'Get-DkimSigningConfig') | Where-Object -Property Enabled -EQ $false + If ($Settings.remediate) { + try { + $DKIM | ForEach-Object { + (New-ExoRequest -tenantid $tenant -cmdlet 'New-DkimSigningConfig' -cmdparams @{ KeySize = 2048; DomainName = $_.Identity; Enabled = $true } -useSystemMailbox $true) + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled DKIM Setup' -sev Info + + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable DKIM. Error: $($_.exception.message)" -sev Error + } + } + + if ($Settings.alert) { + + if ($DKIM) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'DKIM is enabled for all available domains' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'DKIM is not enabled for all available domains' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DKIM' -FieldValue [bool]$DKIM -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 new file mode 100644 index 000000000000..b17bccf7290c --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 @@ -0,0 +1,27 @@ +function Invoke-CIPPStandardAnonReportDisable { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/reportSettings' -tenantid $Tenant -AsApp $true + If ($Settings.remediate) { + try { + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/reportSettings' -Type patch -Body '{"displayConcealedNames": false}' -ContentType 'application/json' -AsApp $true + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Anonymous Reports Disabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable anonymous reports. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($CurrentInfo.displayConcealedNames -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Anonymous Reports is disabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Anonymous Reports is not disabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'AnonReport' -FieldValue [bool]$CurrentInfo.displayConcealedNames -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 new file mode 100644 index 000000000000..63bbdafe4269 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 @@ -0,0 +1,45 @@ +function Invoke-CIPPStandardAuditLog { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + + $AuditLogEnabled = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AdminAuditLogConfig').UnifiedAuditLogIngestionEnabled + + If ($Settings.remediate) { + Write-Host 'Time to remediate' + $DehydratedTenant = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').IsDehydrated + if ($DehydratedTenant) { + New-ExoRequest -tenantid $Tenant -cmdlet 'Enable-OrganizationCustomization' + } + + try { + if ($AuditLogEnabled) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Unified Audit Log already enabled.' -sev Info + } else { + $AdminAuditLogParams = @{ + UnifiedAuditLogIngestionEnabled = $true + } + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AdminAuditLogConfig' -cmdParams $AdminAuditLogParams + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Unified Audit Log Enabled.' -sev Info + } + + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Unified Audit Log. Error: $ErrorMessage" -sev Error + } + } + if ($Settings.alert) { + + if ($AuditLogEnabled) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Unified Audit Log is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Unified Audit Log is not enabled' -sev Alert + } + } + if ($Settings.report) { + + Add-CIPPBPAField -FieldName 'AuditLog' -FieldValue [bool]$AuditLogEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 new file mode 100644 index 000000000000..429466241b5c --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 @@ -0,0 +1,29 @@ +function Invoke-CIPPStandardAutoExpandArchive { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').AutoExpandingArchiveEnabled + If ($Settings.remediate) { + try { + if (!$currentstate) { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{AutoExpandingArchive = $true } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Added Auto Expanding Archive.' -sev Info + } + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Auto Expanding Archives Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($AuditLogEnabled) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Auto Expanding Archives is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Auto Expanding Archives is not enabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'AutoExpandingArchive' -FieldValue [bool]$CurrentState.AutoExpandingArchiveEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAzurePortal.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAzurePortal.ps1 new file mode 100644 index 000000000000..f0c5622b80e7 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAzurePortal.ps1 @@ -0,0 +1,10 @@ +function Invoke-CIPPStandardAzurePortal { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Azure Portal disablement is no longer functional. Please remove this standard.' -sev Error + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccess.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccess.ps1 new file mode 100644 index 000000000000..838a3c0efbbc --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccess.ps1 @@ -0,0 +1,25 @@ +function Invoke-CIPPStandardConditionalAccess { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + + $APINAME = 'Standards' + + foreach ($Template in $Settings.TemplateList) { + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$($Template.value)'" + $JSONObj = (Get-AzDataTableEntity @Table -Filter $Filter).JSON + $CAPolicy = New-CIPPCAPolicy -TenantFilter $tenant -state $request.body.NewState -RawJSON $JSONObj -Overwrite $true -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update conditional access rule $($JSONObj.displayName): $($_.exception.message)" -sev 'Error' + } + } + + + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 new file mode 100644 index 000000000000..4c219d329ba6 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 @@ -0,0 +1,36 @@ +function Invoke-CIPPStandardDelegateSentItems { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{ RecipientTypeDetails = @('UserMailbox', 'SharedMailbox') } | Where-Object { $_.MessageCopyForSendOnBehalfEnabled -eq $false -or $_.MessageCopyForSentAsEnabled -eq $false } + + If ($Settings.remediate) { + try { + $Mailboxes | ForEach-Object { + try { + $username = $_.UserPrincipalName + New-ExoRequest -tenantid $Tenant -cmdlet 'set-mailbox' -cmdParams @{Identity = $_.GUID ; MessageCopyForSendOnBehalfEnabled = $True; MessageCopyForSentAsEnabled = $True } -anchor $username + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not enable delegate sent item style for $($username): $($_.Exception.message)" -sev Warn + } + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Delegate Sent Items Style enabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Delegate Sent Items Style. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($Mailboxes) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Delegate Sent Items Style is not enabled for $($mailboxes.count) users" -sev Alert + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Delegate Sent Items Style is enabled' -sev Info + } + } + if ($Settings.report) { + $Filtered = $Mailboxes | Select-Object -Property UserPrincipalName, MessageCopyForSendOnBehalfEnabled, MessageCopyForSentAsEnabled + Add-CIPPBPAField -FieldName 'DelegateSentItems' -FieldValue $Filtered -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 new file mode 100644 index 000000000000..975368668560 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 @@ -0,0 +1,34 @@ +function Invoke-CIPPStandardDeletedUserRentention { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + + If ($Settings.remediate) { + try { + $body = '{"deletedUserPersonalSiteRetentionPeriodInDays": 365}' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type PATCH -Body $body -ContentType 'application/json' + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Set deleted user rentention of OneDrive to 1 year' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set deleted user rentention of OneDrive to 1 year: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + if ($CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays -eq 365) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Deleted user rentention of OneDrive is set to 1 year' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Deleted user rentention of OneDrive is not set to 1 year' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays -eq 365) { + $CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays = $true + } else { + $CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays = $false + } + Add-CIPPBPAField -FieldName 'DeletedUserRentention' -FieldValue [bool]$CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 new file mode 100644 index 000000000000..1037a1ba6a20 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 @@ -0,0 +1,94 @@ +function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + function GetTenantRequestXml { + return @' + + + + + + + + + + + + + +'@ + } + + function GetDisableAddShortcutsToOneDriveXml { + param( + [string]$identity + ) + + # the json object gives us a space and a newline :( + $identity = $identity.Replace(' ', '') + $identity = $identity.Replace("`n", ' ') + return @" + + + + true + + + + + + +"@ + } + + $log = @{ + API = 'Standards' + tenant = $tenant + message = '' + sev = 'Info' + } + + try { + $OnMicrosoft = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains?$top=999' -tenantid $tenant | + Where-Object -Property isInitial -EQ $true).id.split('.') | Select-Object -First 1 + $AdminUrl = "https://$($OnMicrosoft)-admin.sharepoint.com" + $graphRequest = @{ + 'scope' = "$AdminURL/.default" + 'tenantid' = $tenant + 'uri' = "$AdminURL/_vti_bin/client.svc/ProcessQuery" + 'type' = 'POST' + 'body' = GetTenantRequestXml + 'ContentType' = 'text/xml' + } + + $response = New-GraphPostRequest @graphRequest + if (!$response.ErrorInfo.ErrorMessage) { + $log.message = 'Received Tenant from Sharepoint' + Write-LogMessage @log + } + + $graphRequest.Body = GetDisableAddShortcutsToOneDriveXml -identity $response._ObjectIdentity_ + $response = New-GraphPostRequest @graphRequest + + if (!$response.ErrorInfo.ErrorMessage) { + $log.message = "Set DisableAddShortcutsToOneDrive to True on $tenant" + } else { + $log.message = "Unable to set DisableAddShortcutsToOneDrive to True ` + on $($Tenant, $Settings): $($response.ErrorInfo.ErrorMessage)" + } + } catch { + $log.message = "Failed to set OneDrive shortcut: $($_.Exception.Message)" + $log.sev = 'Error' + } + + Write-LogMessage @log + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuth.ps1 new file mode 100644 index 000000000000..b4bb0e779681 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuth.ps1 @@ -0,0 +1,8 @@ +function Invoke-CIPPStandardDisableBasicAuth { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + Write-LogMessage -API 'Standards' -tenant $tenant -message "Basic Authentication is disabled by default. SMTP authentication is still allowed. Please use the standard 'Disable SMTP Basic Authentication' to disable" -sev Info +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 new file mode 100644 index 000000000000..e16637950b76 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 @@ -0,0 +1,27 @@ +function Invoke-CIPPStandardDisableBasicAuthSMTP { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + try { + $Request = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-TransportConfig' -cmdParams @{ SmtpClientAuthenticationDisabled = $true } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled SMTP Basic Authentication' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable SMTP Basic Authentication: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-TransportConfig' + if ($CurrentInfo.SmtpClientAuthenticationDisabled) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'SMTP Basic Authentication is disabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'SMTP Basic Authentication is not disabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DisableBasicAuthSMTP' -FieldValue [bool]$CurrentInfo.SmtpClientAuthenticationDisabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 new file mode 100644 index 000000000000..9729b4b163a7 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 @@ -0,0 +1,38 @@ +function Invoke-CIPPStandardDisableGuestDirectory { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $Tenant + + If ($Settings.remediate) { + + + try { + $body = '{guestUserRoleId: "2af84b1e-32c8-42b7-82bc-daa82404023b"}' + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type patch -Body $body -ContentType 'application/json') + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled Guest access to directory information.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable Guest access to directory information.: $($_.exception.message)" -sev 'Error' + } + } + + if ($Settings.alert) { + + if ($CurrentInfo.guestUserRoleId -eq '2af84b1e-32c8-42b7-82bc-daa82404023b') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guest access to directory information is disabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guest access to directory information is not disabled.' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentInfo.guestUserRoleId -eq '2af84b1e-32c8-42b7-82bc-daa82404023b') { + $CurrentInfo.guestUserRoleId = $true + } else { + $CurrentInfo.guestUserRoleId = $false + } + Add-CIPPBPAField -FieldName 'DisableGuestDirectory' -FieldValue [bool]$CurrentInfo.guestUserRoleId -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 new file mode 100644 index 000000000000..bcb286cc7677 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 @@ -0,0 +1,33 @@ +function Invoke-CIPPStandardDisableGuests { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $lookup = (Get-Date).AddDays(-90).ToUniversalTime().ToString('o') + $GraphRequest = New-GraphgetRequest -uri "https://graph.microsoft.com/beta/users?`$filter=(signInActivity/lastSignInDateTime le $lookup)&`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled" -scope 'https://graph.microsoft.com/.default' -tenantid $Tenant | Where-Object { $_.userType -EQ 'Guest' -and $_.AccountEnabled -EQ $true } + + If ($Settings.remediate) { + try { + foreach ($guest in $GraphRequest) { + New-GraphPostRequest -type Patch -tenantid $tenant -uri "https://graph.microsoft.com/beta/users/$($guest.id)" -body '{"accountEnabled":"false"}' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Disabling guest $($guest.UserPrincipalName) ($($guest.id))" -sev Info + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled guests accounts with a login longer than 90 days ago.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable guests older than 90 days: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($GraphRequest) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Guests accounts with a login longer than 90 days ago: $($GraphRequest.count)" -sev Alert + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'No guests accounts with a login longer than 90 days ago.' -sev Info + } + } + if ($Settings.report) { + $filtered = $GraphRequest | Select-Object -Property UserPrincipalName, id, signInActivity, mail, userType, accountEnabled + Add-CIPPBPAField -FieldName 'DisableGuests' -FieldValue $filtered -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 new file mode 100644 index 000000000000..125025a40b83 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 @@ -0,0 +1,50 @@ +function Invoke-CIPPStandardDisableM365GroupUsers { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/settings' -tenantid $tenant) | Where-Object -Property displayname -EQ 'Group.unified' + + If ($Settings.remediate) { + try { + if (!$CurrentState) { + #if no current configuration is found, we set it to the default template supplied by MS. + $CurrentState = '{"id":"","displayName":"Group.Unified","templateId":"62375ab9-6b52-47ed-826b-58e47e0e304b","values":[{"name":"NewUnifiedGroupWritebackDefault","value":"true"},{"name":"EnableMIPLabels","value":"false"},{"name":"CustomBlockedWordsList","value":""},{"name":"EnableMSStandardBlockedWords","value":"false"},{"name":"ClassificationDescriptions","value":""},{"name":"DefaultClassification","value":""},{"name":"PrefixSuffixNamingRequirement","value":""},{"name":"AllowGuestsToBeGroupOwner","value":"false"},{"name":"AllowGuestsToAccessGroups","value":"true"},{"name":"GuestUsageGuidelinesUrl","value":""},{"name":"GroupCreationAllowedGroupId","value":""},{"name":"AllowToAddGuests","value":"true"},{"name":"UsageGuidelinesUrl","value":""},{"name":"ClassificationList","value":""},{"name":"EnableGroupCreation","value":"true"}]}' + (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/settings/$($CurrentState.id)" -Type POST -Body $CurrentState -ContentType 'application/json') + $CurrentState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/settings' -tenantid $tenant) | Where-Object -Property displayname -EQ 'Group.unified' + } + ($CurrentState.values | Where-Object { $_.name -eq 'EnableGroupCreation' }).value = 'false' + $body = "{values : $($CurrentState.values | ConvertTo-Json -Compress)}" + (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/settings/$($CurrentState.id)" -Type patch -Body $body -ContentType 'application/json') + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Standards API: Disabled users from creating M365 Groups.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable users from creating M365 Groups: $($_.exception.message)" -sev 'Error' + } + } + if ($Settings.alert) { + + if ($CurrentState) { + if (($CurrentState.values | Where-Object { $_.name -eq 'EnableGroupCreation' }).value -eq 'false') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Users are disabled from creating M365 Groups.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Users are not disabled from creating M365 Groups.' -sev Alert + } + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Users are not disabled from creating M365 Groups.' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentState) { + if (($CurrentState.values | Where-Object { $_.name -eq 'EnableGroupCreation' }).value -eq 'false') { + $CurrentState = $true + } else { + $CurrentState = $false + } + } else { + $CurrentState = $false + } + Add-CIPPBPAField -FieldName 'DisableM365GroupUsers' -FieldValue [bool]$CurrentState -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 new file mode 100644 index 000000000000..2f438e417605 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardDisableReshare { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + + try { + $body = '{"isResharingByExternalUsersEnabled": "False"}' + $Request = New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body $body -ContentType 'application/json' + Write-Host ($Request | ConvertTo-Json) + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled guests from resharing files' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable guests from resharing files: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + if ($CurrentInfo.isResharingByExternalUsersEnabled -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guests are not allowed to reshare files' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guests are allowed to reshare files' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DisableReshare' -FieldValue [bool]$CurrentInfo.isResharingByExternalUsersEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 new file mode 100644 index 000000000000..75facbab7757 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 @@ -0,0 +1,32 @@ +function Invoke-CIPPStandardDisableSecurityGroupUsers { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + + try { + $body = '{"defaultUserRolePermissions":{"allowedToCreateSecurityGroups":false}}' + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type patch -Body $body -ContentType 'application/json') + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Standards API: Disabled users from creating Security Groups.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable users from creating Security Groups: $($_.exception.message)" -sev 'Error' + } + } + + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $Tenant + if ($CurrentInfo.defaultUserRolePermissions.allowedToCreateSecurityGroups -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Users are not allowed to create Security Groups.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Users are allowed to create Security Groups.' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DisableSecurityGroupUsers' -FieldValue [bool]$CurrentInfo.defaultUserRolePermissions.allowedToCreateSecurityGroups -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 new file mode 100644 index 000000000000..c90b55962a58 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 @@ -0,0 +1,10 @@ +function Invoke-CIPPStandardDisableSelfServiceLicenses { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Self Service Licenses cannot be disabled' -sev Error + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 new file mode 100644 index 000000000000..77e7295aaca8 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 @@ -0,0 +1,29 @@ +function Invoke-CIPPStandardDisableSharedMailbox { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $SharedMailboxList = (New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($Tenant)/Mailbox?`$filter=ExchangeUserAccountControl ne 'accountdisabled'" -Tenantid $tenant -scope ExchangeOnline | Where-Object { $_.RecipientTypeDetails -EQ 'SharedMailbox' -or $_.RecipientTypeDetails -eq 'SchedulingMailbox' }) + If ($Settings.remediate) { + try { + $SharedMailboxList | ForEach-Object { + New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/users/$($_.ObjectKey)" -type 'PATCH' -body '{"accountEnabled":"false"}' -tenantid $tenant + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'AAD Accounts for shared mailboxes disabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable AAD accounts for shared mailboxes. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($SharedMailboxList) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Shared mailboxes with enabled accounts: $($SharedMailboxList.count)" -sev Alert + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'No AAD accounts enables for shared mailboxes.' -sev Info + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DisableSharedMailbox' -FieldValue $SharedMailboxList -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 new file mode 100644 index 000000000000..55cde0260efc --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 @@ -0,0 +1,28 @@ +function Invoke-CIPPStandardDisableTenantCreation { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + try { + $body = '{"defaultUserRolePermissions":{"allowedToCreateTenants":false}}' + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type patch -Body $body -ContentType 'application/json') + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Standards API: Disabled users from creating tenants.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable users from creating tenants: $($_.exception.message)" -sev 'Error' + } + } + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $Tenant + if ($CurrentInfo.defaultUserRolePermissions.allowedToCreateTenants -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Users are not allowed to create tenants.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Users are allowed to create tenants.' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DisableTenantCreation' -FieldValue [bool]$CurrentInfo.defaultUserRolePermissions.allowedToCreateTenants -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 new file mode 100644 index 000000000000..3943cbc38d43 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 @@ -0,0 +1,28 @@ +function Invoke-CIPPStandardDisableUserSiteCreate { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + try { + $body = '{"isSiteCreationEnabled": false}' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled standard users from creating sites' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable standard users from creating sites: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + if ($CurrentInfo.isSiteCreationEnabled -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Standard users are not allowed to create sites' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Standard users are allowed to create sites' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DisableUserSiteCreate' -FieldValue [bool]$CurrentInfo.isSiteCreationEnabled -StoreAs bool -Tenant $tenant + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 new file mode 100644 index 000000000000..3c7332d68d7c --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 @@ -0,0 +1,29 @@ +function Invoke-CIPPStandardDisableViva { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $currentsetting = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/organization/$tenant/settings/peopleInsights" -tenantid $Tenant -AsApp $true + If ($Settings.remediate) { + try { + New-GraphPOSTRequest -Uri "https://graph.microsoft.com/beta/organization/$tenant/settings/peopleInsights" -tenantid $Tenant -AsApp $true -Type PATCH -Body '{"isEnabledInOrganization": false}' -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled Viva insights' -sev Info + + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable Viva for all users Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($currentsetting.isEnabled -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Viva is disabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Viva is not disabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DisableViva' -FieldValue [bool]$currentsetting.isEnabled -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 new file mode 100644 index 000000000000..229db4b77171 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 @@ -0,0 +1,78 @@ +function Invoke-CIPPStandardEnableAppConsentRequests { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/adminConsentRequestPolicy' -tenantid $Tenant + + If ($Settings.remediate) { + try { + # Get current state + + # Change state to enabled with default settings + $CurrentInfo.isEnabled = 'true' + $CurrentInfo.notifyReviewers = 'true' + $CurrentInfo.remindersEnabled = 'true' + $CurrentInfo.requestDurationInDays = 30 + + # Roles from standards table + $RolesToAdd = $Settings.ReviewerRoles.value + $RoleNames = $Settings.ReviewerRoles.label -join ', ' + + # Set default if no roles are selected + if (!$RolesToAdd) { + $RolesToAdd = @('62e90394-69f5-4237-9190-012177145e10') + $RoleNames = '(Default) Global Administrator' + } + + $NewReviewers = foreach ($Role in $RolesToAdd) { + @{ + query = "/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$Role'" + queryType = 'MicrosoftGraph' + queryRoot = 'null' + } + } + + # Add existing reviewers + $Reviewers = [System.Collections.Generic.List[object]]::new() + foreach ($Reviewer in $CurrentInfo.reviewers) { + $RoleFound = $false + foreach ($Role in $RolesToAdd) { + if ($Reviewer.query -match $Role -or $Reviewers.query -contains $Reviewer.query) { + $RoleFound = $true + } + } + if (!$RoleFound) { + $Reviewers.add($Reviewer) + } + } + + # Add new reviewer roles + foreach ($NewReviewer in $NewReviewers) { + $Reviewers.add($NewReviewer) + } + + # Update reviewer list + $CurrentInfo.reviewers = @($Reviewers) + $body = (ConvertTo-Json -Compress -Depth 10 -InputObject $CurrentInfo) + + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/adminConsentRequestPolicy' -Type put -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Enabled App consent admin requests for the following roles: $RoleNames" -sev Info + + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable App consent admin requests. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($CurrentInfo.isEnabled -eq 'true') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'App consent admin requests are enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'App consent admin requests are disabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'EnableAppConsentAdminRequests' -FieldValue [bool]$CurrentInfo.isEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 new file mode 100644 index 000000000000..1c7ff1337f4e --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardEnableFIDO2 { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + + try { + $body = '{"@odata.type":"#microsoft.graph.fido2AuthenticationMethodConfiguration","id":"Fido2","includeTargets":[{"id":"all_users","isRegistrationRequired":false,"targetType":"group","displayName":"All users"}],"excludeTargets":[],"isAttestationEnforced":true,"isSelfServiceRegistrationAllowed":true,"keyRestrictions":{"aaGuids":[],"enforcementType":"block","isEnforced":false},"state":"enabled"}' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationmethodspolicy/authenticationMethodConfigurations/Fido2' -Type patch -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled FIDO2 Support' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable FIDO2 Support: $($_.exception.message)" -sev Error + } + } + + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationmethodspolicy/authenticationMethodConfigurations/Fido2' -tenantid $Tenant + if ($CurrentInfo.state -eq 'enabled') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'FIDO2 Support is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'FIDO2 Support is not enabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'EnableFIDO2' -FieldValue [bool]$CurrentInfo.state -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 new file mode 100644 index 000000000000..92bfc8b7a6db --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 @@ -0,0 +1,33 @@ +function Invoke-CIPPStandardEnableOnlineArchiving { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $MailboxesNoArchive = (New-ExoRequest -tenantid $tenant -cmdlet 'get-mailbox' -cmdparams @{ Filter = 'ArchiveGuid -Eq "00000000-0000-0000-0000-000000000000" -AND RecipientTypeDetails -Eq "UserMailbox"' }) + If ($Settings.remediate) { + + + try { + $MailboxesNoArchive | ForEach-Object { + (New-ExoRequest -tenantid $tenant -cmdlet 'enable-Mailbox' -cmdparams @{ Identity = $_.UserPrincipalName; Archive = $true }) + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled Online Archiving for all accounts' -sev Info + + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to Enable Online Archiving for all accounts Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($MailboxesNoArchive) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Mailboxes without Online Archiving: $($MailboxesNoArchive.count)" -sev Alert + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'All mailboxes have Online Archiving enabled' -sev Info + } + } + if ($Settings.report) { + $filtered = $MailboxesNoArchive | Select-Object -Property UserPrincipalName, Archive + Add-CIPPBPAField -FieldName 'EnableOnlineArchiving' -FieldValue $MailboxesNoArchive -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 new file mode 100644 index 000000000000..9182323cda87 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 @@ -0,0 +1,34 @@ +function Invoke-CIPPStandardExConnector { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + $APINAME = 'Standards' + foreach ($Template in $Settings.TemplateList) { + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'ExConnectorTemplate' and RowKey eq '$($Template.value)'" + $connectorType = (Get-AzDataTableEntity @Table -Filter $Filter).direction + $RequestParams = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json + $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet "Get-$($ConnectorType)connector" | Where-Object -Property Identity -EQ $RequestParams.name + if ($Existing) { + $RequestParams | Add-Member -NotePropertyValue $Existing.Identity -NotePropertyName Identity -Force + $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "Set-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true + Write-LogMessage -API $APINAME -tenant $Tenant -message "Updated transport rule for $($Tenant, $Settings)" -sev info + } else { + $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true + Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($Tenant, $Settings)" -sev info + } + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Exchange Connector Rule: $($_.exception.message)" -sev 'Error' + } + + } + + } + + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 new file mode 100644 index 000000000000..7d52d6c4eb74 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardExcludedfileExt { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $Exts = $Settings.ext -split ',' + If ($Settings.remediate) { + + + try { + $body = ConvertTo-Json -InputObject @{ excludedFileExtensionsForSyncApp = @($Exts) } + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Added $($Settings.ext) to excluded synced files" -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to add $($Settings.ext) to excluded synced files: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + if ($CurrentInfo.excludedFileExtensionsForSyncApp -contains $Exts) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Excluded synced files contains $($Settings.ext)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Excluded synced files does not contain $($Settings.ext)" -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'ExcludedfileExt' -FieldValue $CurrentInfo.excludedFileExtensionsForSyncApp -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 new file mode 100644 index 000000000000..f07e54320d72 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 @@ -0,0 +1,58 @@ +function Invoke-CIPPStandardGroupTemplate { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + foreach ($Template in $Settings.TemplateList) { + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$($Template.value)'" + $groupobj = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json + $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($Tenant)" } + $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant | Where-Object -Property displayName -EQ $groupobj.displayname + if (!$CheckExististing) { + if ($groupobj.groupType -in 'Generic', 'azurerole', 'dynamic') { + + $BodyToship = [pscustomobject] @{ + 'displayName' = $groupobj.Displayname + 'description' = $groupobj.Description + 'mailNickname' = $groupobj.username + mailEnabled = [bool]$false + securityEnabled = [bool]$true + isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ 'AzureRole') + + } + if ($groupobj.membershipRules) { + $BodyToship | Add-Member -NotePropertyName 'membershipRule' -NotePropertyValue ($groupobj.membershipRules) + $BodyToship | Add-Member -NotePropertyName 'groupTypes' -NotePropertyValue @('DynamicMembership') + $BodyToship | Add-Member -NotePropertyName 'membershipRuleProcessingState' -NotePropertyValue 'On' + } + $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose + } else { + $Params = @{ + Name = $groupobj.Displayname + Alias = $groupobj.username + Description = $groupobj.Description + PrimarySmtpAddress = $email + Type = $groupobj.groupType + RequireSenderAuthenticationEnabled = [bool]!$groupobj.AllowExternal + } + $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet 'New-DistributionGroup' -cmdParams $params + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Standards' -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) " -Sev 'Info' + + } else { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Standards' -tenant $tenant -message "Group exists $($groupobj.displayname). Did not create" -Sev 'Info' + + } + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create group: $($_.exception.message)" -sev 'Error' + } + } + + + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 new file mode 100644 index 000000000000..d6676fc437ec --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -0,0 +1,86 @@ +function Invoke-CIPPStandardIntuneTemplate { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + Write-Host 'starting template deploy' + $APINAME = 'Standards' + foreach ($Template in $Settings.TemplateList) { + Write-Host 'working on template deploy' + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'IntuneTemplate'" + $Request = @{body = $null } + $Request.body = (Get-AzDataTableEntity @Table -Filter $Filter | Where-Object -Property RowKey -Like "$($template.value)*").JSON | ConvertFrom-Json + $displayname = $request.body.Displayname + $description = $request.body.Description + $RawJSON = $Request.body.RawJSON + + switch ($Request.body.Type) { + 'Admin' { + $TemplateTypeURL = 'groupPolicyConfigurations' + $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($displayname -in $CheckExististing.displayName) { + $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname + $ExistingData = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/definitionValues" -tenantid $tenant + $DeleteJson = $RawJSON | ConvertFrom-Json -Depth 10 + $DeleteJson.deletedIds = @($ExistingData.id) + $DeleteJson.added = @() + $DeleteJson = ConvertTo-Json -Depth 10 -InputObject $DeleteJson + $DeleteRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $DeleteJson + $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($Displayname) to template defaults" -Sev 'info' + + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $CreateBody + $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname) to template defaults" -Sev 'info' + + } + } + 'Device' { + $TemplateTypeURL = 'deviceConfigurations' + $PolicyName = ($RawJSON | ConvertFrom-Json).displayName + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($PolicyName -in $CheckExististing.displayName) { + $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($PolicyName) to template defaults" -Sev 'info' + + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' + + } + } + 'Catalog' { + $TemplateTypeURL = 'configurationPolicies' + $PolicyName = ($RawJSON | ConvertFrom-Json).Name + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($PolicyName -in $CheckExististing.name) { + $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON + + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' + } + } + + } + + if ($Settings.AssignTo) { + Write-Host "Assigning Policy to $($Settings.AssignTo) the create ID is $($CreateRequest)" + Set-CIPPAssignedPolicy -PolicyId $CreateRequest.id -TenantFilter $tenant -GroupName $Settings.AssignTo -Type $TemplateTypeURL + } + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully added Intune Template policy for $($Tenant)" -sev 'Info' + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Intune Template: $($_.exception.message)" -sev 'Error' + } + } + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFA.ps1 new file mode 100644 index 000000000000..32158bf5de70 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFA.ps1 @@ -0,0 +1,9 @@ +function Invoke-CIPPStandardLegacyMFA { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Per user MFA APIs have been disabled.' -sev Info + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 new file mode 100644 index 000000000000..08f43267469f --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 @@ -0,0 +1,9 @@ +function Invoke-CIPPStandardLegacyMFACleanup { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Per User MFA APIs have been disabled.' -sev Info + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 new file mode 100644 index 000000000000..73e59b351a78 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 @@ -0,0 +1,54 @@ +function Invoke-CIPPStandardMailContacts { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $TenantID = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/organization' -tenantid $tenant) + + If ($Settings.remediate) { + + $contacts = $settings + try { + $Body = [pscustomobject]@{} + switch ($Contacts) { + { $Contacts.MarketingContact } { $body | Add-Member -NotePropertyName marketingNotificationEmails -NotePropertyValue @($Contacts.MarketingContact) } + { $Contacts.SecurityContact } { $body | Add-Member -NotePropertyName securityComplianceNotificationMails -NotePropertyValue @($Contacts.SecurityContact) } + { $Contacts.TechContact } { $body | Add-Member -NotePropertyName technicalNotificationMails -NotePropertyValue @($Contacts.TechContact) } + { $Contacts.GeneralContact } { $body | Add-Member -NotePropertyName privacyProfile -NotePropertyValue @{contactEmail = $Contacts.GeneralContact } } + } + Write-Host (ConvertTo-Json -InputObject $body) + New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/organization/$($TenantID.id)" -Type patch -Body (ConvertTo-Json -InputObject $body) -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Contact email's set." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set contact emails: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/organization/$($TenantID.id)" -tenantid $Tenant + if ($CurrentInfo.marketingNotificationEmails -eq $Contacts.MarketingContact) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Marketing contact email is set to $($Contacts.MarketingContact)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Marketing contact email is not set to $($Contacts.MarketingContact)" -sev Alert + } + if ($CurrentInfo.securityComplianceNotificationMails -eq $Contacts.SecurityContact) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Security contact email is set to $($Contacts.SecurityContact)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Security contact email is not set to $($Contacts.SecurityContact)" -sev Alert + } + if ($CurrentInfo.technicalNotificationMails -eq $Contacts.TechContact) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Technical contact email is set to $($Contacts.TechContact)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Technical contact email is not set to $($Contacts.TechContact)" -sev Alert + } + if ($CurrentInfo.privacyProfile.contactEmail -eq $Contacts.GeneralContact) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "General contact email is set to $($Contacts.GeneralContact)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "General contact email is not set to $($Contacts.GeneralContact)" -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'MailContacts' -FieldValue $CurrentInfo -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardModernAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardModernAuth.ps1 new file mode 100644 index 000000000000..51c25c4da8b9 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardModernAuth.ps1 @@ -0,0 +1,10 @@ +function Invoke-CIPPStandardModernAuth { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Modern Authentication is enabled by default. This standard is no longer required.' -sev Info + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 new file mode 100644 index 000000000000..f9a6a0710d44 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 @@ -0,0 +1,37 @@ +function Invoke-CIPPStandardNudgeMFA { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -tenantid $Tenant + + If ($Settings.remediate) { + $status = if ($Settings.enable -and $Settings.disable) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'You cannot both enable and disable the Nudge MFA setting' -sev Error + Exit + } elseif ($Settings.enable) { 'enabled' } else { 'disabled' } + Write-Output $status + try { + $Body = $CurrentInfo + $body.registrationEnforcement.authenticationMethodsRegistrationCampaign.state = $status + $body = ConvertTo-Json -Depth 10 -InputObject ($body | Select-Object registrationEnforcement) + New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy" -Type patch -Body $body -ContentType "application/json" + Write-LogMessage -API "Standards" -tenant $tenant -message "$status Authenticator App Nudge" -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to $status Authenticator App Nudge: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq 'enabled') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Authenticator App Nudge is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Authenticator App Nudge is not enabled' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq 'enabled') { $actualstate = $true } else { $actualstate = $false } + Add-CIPPBPAField -FieldName 'NudgeMFA' -FieldValue [bool]$actualstate -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 new file mode 100644 index 000000000000..a3ecdb371327 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 @@ -0,0 +1,50 @@ +function Invoke-CIPPStandardOauthConsent { + <# + .FUNCTIONALITY + Internal + #> + param($tenant, $settings) { + $State = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $tenant) + + If ($Settings.remediate) { + $AllowedAppIdsForTenant = $Settings.AllowedApps -split ',' + try { + if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('ManagePermissionGrantsForSelf.cipp-1sent-policy')) { + $Existing = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies/' -tenantid $tenant) | Where-Object -Property id -EQ 'cipp-consent-policy' + if (!$Existing) { + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies' -Type POST -Body '{ "id":"cipp-consent-policy", "displayName":"Application Consent Policy", "description":"This policy controls the current application consent policies."}' -ContentType 'application/json' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies/cipp-consent-policy/includes' -Type POST -Body '{"permissionClassification":"all","permissionType":"delegated","clientApplicationIds":["d414ee2d-73e5-4e5b-bb16-03ef55fea597"]}' -ContentType 'application/json' + } + try { + foreach ($AllowedApp in $AllowedAppIdsForTenant) { + Write-Host "$AllowedApp" + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies/cipp-consent-policy/includes' -Type POST -Body ('{"permissionType": "delegated","clientApplicationIds": ["' + $AllowedApp + '"]}') -ContentType 'application/json' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies/cipp-consent-policy/includes' -Type POST -Body ('{ "permissionType": "Application", "clientApplicationIds": ["' + $AllowedApp + '"] }') -ContentType 'application/json' + } + } catch { + "Could not add exclusions, probably already exist: $($_)" + } + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["managePermissionGrantsForSelf.cipp-consent-policy"]}' -ContentType 'application/json' + } + if ($AllowedAppIdsForTenant) { + } + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode has been enabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Application Consent Mode Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -eq 'managePermissionGrantsForSelf.cipp-consent-policy') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode is not enabled.' -sev Alert + } + } + if ($Settings.report) { + if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -eq 'managePermissionGrantsForSelf.cipp-consent-policy') { $UserQuota = $true } else { $UserQuota = $false } + Add-CIPPBPAField -FieldName 'OauthConsent' -FieldValue [bool]$UserQuota -StoreAs bool -Tenant $tenant + } + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 new file mode 100644 index 000000000000..e0f627a41ddc --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 @@ -0,0 +1,35 @@ +function Invoke-CIPPStandardOauthConsentLowSec { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $State = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $tenant) + If ($Settings.remediate) { + try { + if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('managePermissionGrantsForSelf.microsoft-user-default-low')) { + Write-Host 'Going to set' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["managePermissionGrantsForSelf.microsoft-user-default-low"]}' -ContentType 'application/json' + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) has been enabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Application Consent Mode (microsoft-user-default-low) Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('managePermissionGrantsForSelf.microsoft-user-default-low')) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) is not enabled.' -sev Alert + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) is enabled.' -sev Info + } + } + if ($Settings.report) { + if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('managePermissionGrantsForSelf.microsoft-user-default-low')) { + $State.permissionGrantPolicyIdsAssignedToDefaultUserRole = $false + } else { + $State.permissionGrantPolicyIdsAssignedToDefaultUserRole = $true + } + Add-CIPPBPAField -FieldName 'OauthConsentLowSec' -FieldValue [bool]$State.permissionGrantPolicyIdsAssignedToDefaultUserRole -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 new file mode 100644 index 000000000000..307ebdfada1c --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 @@ -0,0 +1,28 @@ +function Invoke-CIPPStandardOutBoundSpamAlert { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + $Contacts = $settings.OutboundSpamContact + try { + New-ExoRequest -tenantid $tenant -cmdlet 'Set-HostedOutboundSpamFilterPolicy' -cmdparams @{ Identity = 'Default'; NotifyOutboundSpam = $true; NotifyOutboundSpamRecipients = $Contacts.OutboundSpamContact } -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $tenant -message "Set outbound spam filter alert to $($Contacts.OutboundSpamContact)" -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not set outbound spam contact to $($Contacts.OutboundSpamContact). $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-HostedOutboundSpamFilterPolicy' -useSystemMailbox $true + if ($CurrentInfo.NotifyOutboundSpam -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Outbound spam filter alert is set to $($CurrentInfo.NotifyOutboundSpamRecipients)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Outbound spam filter alert is not set' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'OutboundSpamAlert' -FieldValue [bool]$CurrentInfo.NotifyOutboundSpam -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 new file mode 100644 index 000000000000..2cd6cb851ba7 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 @@ -0,0 +1,46 @@ +function Invoke-CIPPStandardPWcompanionAppAllowedState { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $authenticatorFeaturesState = (New-GraphGetRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -Type GET) + If ($Settings.remediate) { + $Setting = $Settings + try { + # Get current state of microsoftAuthenticator policy + # Remove number matching from featureSettings because this is now Microsoft enforced and shipping it returns an error + $authenticatorFeaturesState.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') + # Define feature body + $featureBody = @{ + state = $Setting.state + includeTarget = [PSCustomObject]@{ + targetType = 'group' + id = 'all_users' + } + excludeTarget = [PSCustomObject]@{ + targetType = 'group' + id = '00000000-0000-0000-0000-000000000000' + } + } + $authenticatorFeaturesState.featureSettings.companionAppAllowedState = $featureBody + $body = $authenticatorFeaturesState | ConvertTo-Json -Depth 3 + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -Type patch -Body $body -ContentType 'application/json') + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled companionAppAllowedState.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable companionAppAllowedState. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($authenticatorFeaturesState.featureSettings.companionAppAllowedState.state -eq 'enabled') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'companionAppAllowedState is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'companionAppAllowedState is not enabled.' -sev Alert + } + } + if ($Settings.report) { + if ($authenticatorFeaturesState.featureSettings.companionAppAllowedState.state -eq 'enabled') { $authstate = $true } else { $authstate = $false } + Add-CIPPBPAField -FieldName 'companionAppAllowedState' -FieldValue [bool]$authstate -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 new file mode 100644 index 000000000000..aecda655774b --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 @@ -0,0 +1,32 @@ +function Invoke-CIPPStandardPWdisplayAppInformationRequiredState { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -tenantid $Tenant + + If ($Settings.remediate) { + try { + $body = @' +{"@odata.type":"#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration","id":"MicrosoftAuthenticator","includeTargets":[{"id":"all_users","isRegistrationRequired":false,"targetType":"group","authenticationMode":"any"}],"excludeTargets":[],"state":"enabled","isSoftwareOathEnabled":false,"featureSettings":{"displayLocationInformationRequiredState":{"state":"enabled","includeTarget":{"id":"all_users","targetType":"group","displayName":"All users"}},"displayAppInformationRequiredState":{"state":"enabled","includeTarget":{"id":"all_users","targetType":"group","displayName":"All users"}},"companionAppAllowedState":{"state":"default","includeTarget":{"id":"all_users","targetType":"group","displayName":"All users"}}}} +'@ + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -Type patch -Body $body -ContentType 'application/json') + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled passwordless with Information and Number Matching.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable passwordless with Information and Number Matching. Error: $($_.exception.message)" -sev 'Error' + } + } + if ($Settings.alert) { + + if ($CurrentInfo.featureSettings.displayAppInformationRequiredState.state -eq 'enabled') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Passwordless with Information and Number Matching is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Passwordless with Information and Number Matching is not enabled.' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentInfo.featureSettings.displayAppInformationRequiredState.state -eq 'enabled') { $authstate = $true } else { $authstate = $false } + Add-CIPPBPAField -FieldName 'PWdisplayAppInformationRequiredState' -FieldValue [bool]$authstate -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWnumberMatchingRequiredState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWnumberMatchingRequiredState.ps1 new file mode 100644 index 000000000000..48b5e602afcb --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWnumberMatchingRequiredState.ps1 @@ -0,0 +1,8 @@ +function Invoke-CIPPStandardPWnumberMatchingRequiredState { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Passwordless with number matching is now enabled by default.' -sev Info +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 new file mode 100644 index 000000000000..3788a12d72b9 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 @@ -0,0 +1,29 @@ +function Invoke-CIPPStandardPasswordExpireDisabled { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $Tenant + If ($Settings.remediate) { + try { + $GraphRequest | Where-Object -Property passwordValidityPeriodInDays -NE '2147483647' | ForEach-Object { + New-GraphPostRequest -type Patch -tenantid $Tenant -uri "https://graph.microsoft.com/beta/domains/$($_.id)" -body '{"passwordValidityPeriodInDays": 2147483647 }' + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled Password Expiration' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable Password Expiration. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $GraphRequest | Where-Object -Property passwordValidityPeriodInDays -NE '2147483647' | ForEach-Object { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Password Expiration is not disabled for $($_.name)" -sev Alert + } + } + if ($Settings.report) { + $DomainswithoutPassExpire = $GraphRequest | Where-Object -Property passwordValidityPeriodInDays -NE '2147483647' + Add-CIPPBPAField -FieldName 'PasswordExpireDisabled' -FieldValue $DomainswithoutPassExpire -StoreAs json -Tenant $tenant + + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 new file mode 100644 index 000000000000..2ce2937ab173 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 @@ -0,0 +1,28 @@ +function Invoke-CIPPStandardRotateDKIM { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $DKIM = (New-ExoRequest -tenantid $tenant -cmdlet 'Get-DkimSigningConfig') | Where-Object { $_.Selector1KeySize -EQ 1024 -and $_.Enabled -eq $true } + If ($Settings.remediate) { + try { + $DKIM | ForEach-Object { + (New-ExoRequest -tenantid $tenant -cmdlet 'Rotate-DkimSigningConfig' -cmdparams @{ KeySize = 2048; Identity = $_.Identity } -useSystemMailbox $true) + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Rotated DKIM' -sev Info + + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to rotate DKIM Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $DKIM | ForEach-Object { + Write-LogMessage -API 'Standards' -tenant $tenant -message "DKIM is not rotated for $($_.Identity)" -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'DKIM' -FieldValue $DKIM -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSSPR.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSSPR.ps1 new file mode 100644 index 000000000000..e6fbdd3181f6 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSSPR.ps1 @@ -0,0 +1,10 @@ +function Invoke-CIPPStandardSSPR { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'SSPR standard is no longer available' -sev Error + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 new file mode 100644 index 000000000000..a0cb61fa8e64 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 @@ -0,0 +1,23 @@ +function Invoke-CIPPStandardSafeSendersDisable { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + try { + $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' | ForEach-Object { + try { + $username = $_.UserPrincipalName + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MailboxJunkEmailConfiguration' -cmdParams @{Identity = $_.GUID ; TrustedRecipientsAndDomains = $null } -anchor $username + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not disbale SafeSenders list for $($username): $($_.Exception.message)" -sev Warn + } + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Safe Senders disabled' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable SafeSenders. Error: $($_.exception.message)" -sev Error + } + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 new file mode 100644 index 000000000000..5d2c0c9c26f7 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardSecurityDefaults { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $SecureDefaultsState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -tenantid $tenant) + If ($Settings.remediate) { + try { + if ($SecureDefaultsState.IsEnabled -ne $true) { + Write-Host "Secure Defaults is disabled. Enabling for $tenant" -ForegroundColor Yellow + $body = '{ "isEnabled": true }' + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -Type patch -Body $body -ContentType 'application/json') + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Standards API: Security Defaults Enabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Security Defaults Error: $($_.exception.message)" -sev 'Error' + } + } + if ($Settings.alert) { + + if ($SecureDefaultsState.IsEnabled -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Security Defaults is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Security Defaults is not enabled.' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'SecurityDefaults' -FieldValue [bool]$SecureDefaultsState.IsEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 new file mode 100644 index 000000000000..cd4972866185 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardSendFromAlias { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + try { + $AdminAuditLogParams = @{ + SendFromAliasEnabled = $true + } + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams $AdminAuditLogParams + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Send from alias Enabled.' -sev Info + + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Send from Alias Standard. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig') + if ($CurrentInfo.SendFromAliasEnabled -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Send from alias is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Send from alias is not enabled.' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'SendFromAlias' -FieldValue [bool]$CurrentInfo.SendFromAliasEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 new file mode 100644 index 000000000000..640cea2d18f0 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 @@ -0,0 +1,35 @@ +function Invoke-CIPPStandardSendReceiveLimitTenant { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $AllMailBoxPlans = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MailboxPlan' | Select-Object DisplayName, MaxSendSize, MaxReceiveSize, GUID + If ($Settings.remediate) { + Write-Host "Time to remediate. Our Settings are $($Settings.SendLimit)MB and $($Settings.ReceiveLimit)MB" + $MaxReceiveSize = [int64]"$($Settings.SendLimit)MB" + $MaxSendSize = [int64]"$($Settings.ReceiveLimit)MB" + + try { + foreach ($MailboxPlan in $AllMailBoxPlans) { + if ($MailboxPlan.MaxSendSize -ne $MaxSendSize -and $MailboxPlan.MaxReceiveSize -ne $MaxReceiveSize) { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MailboxPlan' -cmdParams @{Identity = $MailboxPlan.GUID; MaxSendSize = $MaxSendSize; MaxReceiveSize = $MaxReceiveSize } -useSystemMailbox $true + } + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully set the tenant send and receive limits ' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set the tenant send and receive limits. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + foreach ($MailboxPlan in $AllMailBoxPlans) { + if ($MailboxPlan.MaxSendSize -ne $MaxSendSize -and $MailboxPlan.MaxReceiveSize -ne $MaxReceiveSize) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant send and receive limits are not set correctly for $($MailboxPlan.DisplayName)" -sev Alert + } + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'SendReceiveLimit' -FieldValue $AllMailBoxPlans -StoreAs json -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 new file mode 100644 index 000000000000..4b8d790f7dcf --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -0,0 +1,32 @@ +function Invoke-CIPPStandardSpoofWarn { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + $status = if ($Settings.enable -and $Settings.disable) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'You cannot both enable and disable the Spoof Warnings setting' -sev Error + Exit + } elseif ($Settings.state -eq 'Enabled' -or $Settings.enable) { $true } else { $false } + try { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ExternalInOutlook' -cmdParams @{ Enabled = $status; } + Write-LogMessage -API 'Standards' -tenant $tenant -message "Spoofing warnings set to $status." -sev Info + + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not set spoofing warnings to $status. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ExternalInOutlook') + if ($CurrentInfo.Enabled -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Spoofing warnings are enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Spoofing warnings are not enabled.' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'SpoofingWarnings' -FieldValue [bool]$CurrentInfo.Enabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 new file mode 100644 index 000000000000..ed6559f29cf2 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 @@ -0,0 +1,43 @@ +function Invoke-CIPPStandardTAP { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationmethodspolicy/authenticationMethodConfigurations/TemporaryAccessPass' -tenantid $Tenant) + + If ($Settings.remediate) { + try { + + $CurrentInfo.state = 'enabled' + $CurrentInfo.isUsableOnce = $Settings.config + $CurrentInfo.minimumLifetimeInMinutes = '60' + $CurrentInfo.maximumLifetimeInMinutes = '480' + $CurrentInfo.defaultLifetimeInMinutes = '60' + $CurrentInfo.defaultLength = '8' + $body = ConvertTo-Json -Depth 10 -InputObject $CurrentInfo + Write-Host "Sending body $body" + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/TemporaryAccessPass' -Type patch -asApp $true -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled Temporary Access Passwords.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable TAP. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($CurrentInfo.state -eq 'enabled') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Temporary Access Passwords is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Temporary Access Passwords is not enabled.' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentInfo.state -eq 'enabled') { + $CurrentInfo.state = $true + } else { + $CurrentInfo.state = $false + } + Add-CIPPBPAField -FieldName 'TemporaryAccessPass' -FieldValue [bool]$CurrentInfo.state -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 new file mode 100644 index 000000000000..794f74f31c8f --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 @@ -0,0 +1,35 @@ +function Invoke-CIPPStandardTransportRuleTemplate { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + foreach ($Template in $Settings.TemplateList) { + Write-Host "working on $($Template.value)" + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$($Template.value)'" + $RequestParams = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json + $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet 'Get-TransportRule' -useSystemMailbox $true | Where-Object -Property Identity -EQ $RequestParams.name + + + try { + if ($Existing) { + Write-Host 'Found existing' + $RequestParams | Add-Member -NotePropertyValue $RequestParams.name -NotePropertyName Identity + $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications) -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set transport rule for $tenant" -sev 'Info' + } else { + Write-Host 'Creating new' + $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications) -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully created transport rule for $tenant" -sev 'Info' + } + + Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($tenantfilter)" -sev 'Debug' + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not create transport rule for $($tenantfilter): $($_.Exception.message)" -sev 'Error' + } + } + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 new file mode 100644 index 000000000000..1098903a7c74 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 @@ -0,0 +1,17 @@ +function Invoke-CIPPStandardUndoOauth { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + try { + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["ManagePermissionGrantsForSelf.microsoft-user-default-legacy"]}' -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode has been disabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set Application Consent Mode to disabled Error: $($_.exception.message)" -sev Error + } + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoSSPR.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoSSPR.ps1 new file mode 100644 index 000000000000..8c89559e8c23 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoSSPR.ps1 @@ -0,0 +1,11 @@ +function Invoke-CIPPStandardUndoSSPR { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'The standard for SSPR is no longer supported.' -sev Error + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 new file mode 100644 index 000000000000..f7a5ff7aa040 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -0,0 +1,60 @@ +function Invoke-CIPPStandardUserSubmissions { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $Policy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ReportSubmissionPolicy' + If ($Settings.remediate) { + if ($Settings.enable -and $Settings.disable) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'You cannot both enable and disable the User Submission policy' -sev Error + Exit + } elseif ($Settings.enable) { + $status = $true + try { + + if ($Policy.length -eq 0) { + New-ExoRequest -tenantid $Tenant -cmdlet 'New-ReportSubmissionPolicy' + Write-LogMessage -API 'Standards' -tenant $tenant -message "User Submission policy set to $status." -sev Info + } else { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ReportSubmissionPolicy' -cmdParams @{ EnableReportToMicrosoft = $status; Identity = $($Policy.Identity); } + Write-LogMessage -API 'Standards' -tenant $tenant -message "User Submission policy set to $status." -sev Info + } + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not set User Submission policy to $status. Error: $($_.exception.message)" -sev Error + } + } else { + $status = $false + try { + $Policy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ReportSubmissionPolicy' + if ($Policy.length -eq 0) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "User Submission policy set to $status." -sev Info + } else { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ReportSubmissionPolicy' -cmdParams @{ EnableReportToMicrosoft = $status; Identity = $($Policy.Identity); EnableThirdPartyAddress = $status; ReportJunkToCustomizedAddress = $status; ReportNotJunkToCustomizedAddress = $status; ReportPhishToCustomizedAddress = $status; } + Write-LogMessage -API 'Standards' -tenant $tenant -message "User Submission policy set to $status." -sev Info + } + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not set User Submission policy to $status. Error: $($_.exception.message)" -sev Error + } + } + } + if ($Settings.alert) { + + if ($Policy.length -eq 0) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission policy is not set.' -sev Alert + } else { + if ($Policy.EnableReportToMicrosoft -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission policy is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission policy is disabled.' -sev Alert + } + } + } + if ($Settings.report) { + if ($Policy.length -eq 0) { + Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant + } else { + Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue [bool]$Policy.EnableReportToMicrosoft -StoreAs bool -Tenant $tenant + } + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 new file mode 100644 index 000000000000..00be3942e2db --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 @@ -0,0 +1,36 @@ +function Invoke-CIPPStandardallowOAuthTokens { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = new-graphgetRequest -uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath' -tenantid $Tenant + If ($Settings.remediate) { + + try { + $CurrentInfo.state = 'enabled' + $body = ($CurrentInfo | ConvertTo-Json -Depth 10) + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath' -Type patch -Body $body -ContentType 'application/json') + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled software OTP/oAuth tokens' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable software OTP/oAuth tokens. Error: $($_.exception.message)" -sev 'Error' + } + } + if ($Settings.alert) { + + if ($CurrentInfo.state -eq 'enabled') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'software OTP/oAuth tokens is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'software OTP/oAuth tokens is not enabled' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentInfo.state -eq 'enabled') { + $CurrentInfo.state = $true + } else { + $CurrentInfo.state = $false + } + Add-CIPPBPAField -FieldName 'softwareOath' -FieldValue [bool]$CurrentInfo.state -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 new file mode 100644 index 000000000000..c7a5958a45d8 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 @@ -0,0 +1,33 @@ +function Invoke-CIPPStandardallowOTPTokens { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = new-graphgetRequest -uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -tenantid $Tenant + + If ($Settings.remediate) { + + try { + $CurrentInfo.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') + $CurrentInfo.isSoftwareOathEnabled = $true + $body = ($CurrentInfo | ConvertTo-Json -Depth 10) + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -Type patch -Body $body -ContentType 'application/json') + + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled MS authenticator OTP/oAuth tokens' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable MS authenticator OTP/oAuth tokens. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($CurrentInfo.isSoftwareOathEnabled) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MS authenticator OTP/oAuth tokens is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MS authenticator OTP/oAuth tokens is not enabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'MSAuthenticator' -FieldValue [bool]$CurrentInfo.isSoftwareOathEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 new file mode 100644 index 000000000000..9a2ccfb0e298 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 @@ -0,0 +1,25 @@ +function Invoke-CIPPStandardcalDefault { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' + foreach ($Mailbox in $Mailboxes) { + try { + New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MailboxFolderStatistics' -cmdParams @{identity = $Mailbox.UserPrincipalName; FolderScope = 'Calendar' } -Anchor $Mailbox.UserPrincipalName | Where-Object { $_.FolderType -eq 'Calendar' } | ForEach-Object { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MailboxFolderPermission' -cmdparams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $Settings.permissionlevel } -Anchor $Mailbox.UserPrincipalName + Write-LogMessage -API 'Standards' -tenant $tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $($Settings.permissionlevel)" -sev Info + } + } + catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($_.exception.message)" -sev Error + } + + } + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Done setting default calendar permissions.' -sev Info + + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 new file mode 100644 index 000000000000..41cd85e43c53 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 @@ -0,0 +1,30 @@ +function Invoke-CIPPStandarddisableMacSync { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + + try { + $body = '{"isMacSyncAppEnabled": false}' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled Mac OneDrive Sync' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable Mac OneDrive Sync: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + if ($CurrentInfo.isMacSyncAppEnabled -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Mac OneDrive Sync is disabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Mac OneDrive Sync is not disabled' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'MacSync' -FieldValue [bool]$CurrentInfo.isMacSyncAppEnabled -StoreAs bool -Tenant $tenant + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardfwdAdminAlerts.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardfwdAdminAlerts.ps1 new file mode 100644 index 000000000000..3ccf767f2525 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardfwdAdminAlerts.ps1 @@ -0,0 +1,11 @@ +function Invoke-CIPPStandardfwdAdminAlerts { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + #This isn't done yet. + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 new file mode 100644 index 000000000000..6d2ece082f77 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardintuneDeviceReg { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $PreviousSetting = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -tenantid $Tenant + + If ($Settings.remediate) { + try { + $PreviousSetting.userDeviceQuota = $Settings.max + $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -Type PUT -Body $NewBody -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Set user device quota to $($Settings.max)" -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set user device quota to $($Settings.max) : $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($PreviousSetting.userDeviceQuota -eq $Settings.max) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "User device quota is set to $($Settings.max)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "User device quota is not set to $($Settings.max)" -sev Alert + } + } + if ($Settings.report) { + if ($PreviousSetting.userDeviceQuota -eq $Settings.max) { $UserQuota = $true } else { $UserQuota = $false } + Add-CIPPBPAField -FieldName 'intuneDeviceReg' -FieldValue [bool]$UserQuota -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 new file mode 100644 index 000000000000..502be8862b12 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardintuneDeviceRetirementDays { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + + try { + $body = @{ DeviceInactivityBeforeRetirementInDays = $Settings.days } | ConvertTo-Json + (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupSettings' -Type PATCH -Body $body -ContentType 'application/json') + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled DeviceInactivityBeforeRetirementInDays.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable DeviceInactivityBeforeRetirementInDays. Error: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupSettings' -tenantid $Tenant) + if ($CurrentInfo.DeviceInactivityBeforeRetirementInDays -eq $Settings.days) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'DeviceInactivityBeforeRetirementInDays is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'DeviceInactivityBeforeRetirementInDays is not enabled.' -sev Alert + } + } + if ($Settings.report) { + if ($PreviousSetting.DeviceInactivityBeforeRetirementInDays -eq $Settings.days) { $UserQuota = $true } else { $UserQuota = $false } + + Add-CIPPBPAField -FieldName 'intuneDeviceRetirementDays' -FieldValue [bool]$UserQuota -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 new file mode 100644 index 000000000000..b4a51c61d070 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardintuneRequireMFA { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $PreviousSetting = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -tenantid $Tenant + + If ($Settings.remediate) { + try { + $PreviousSetting.multiFactorAuthConfiguration = '1' + $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -Type PUT -Body $NewBody -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Set required to use MFA when joining Intune Devices' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set require to use MFA when joining Intune Devices: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($PreviousSetting.multiFactorAuthConfiguration -eq 'required') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Require to use MFA when joining Intune Devices is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Require to use MFA when joining Intune Devices is not enabled.' -sev Alert + } + } + if ($Settings.report) { + if ($PreviousSetting.multiFactorAuthConfiguration -eq 'required') { $UserQuota = $true } else { $UserQuota = $false } + Add-CIPPBPAField -FieldName 'intuneRequireMFA' -FieldValue [bool]$UserQuota -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 new file mode 100644 index 000000000000..7ae60c772a41 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 @@ -0,0 +1,31 @@ +function Invoke-CIPPStandardlaps { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $PreviousSetting = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -tenantid $Tenant + + If ($Settings.remediate) { + + try { + $previoussetting.localadminpassword.isEnabled = $true + $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -Type PUT -Body $newBody -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'LAPS has been enabled.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set LAPS: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($PreviousSetting.localadminpassword.isEnabled -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'LAPS is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'LAPS is not enabled.' -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'laps' -FieldValue [bool]$PreviousSetting.localadminpassword.isEnabled -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 new file mode 100644 index 000000000000..e7e177a3cdce --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 @@ -0,0 +1,28 @@ +function Invoke-CIPPStandardsharingCapability { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + + If ($Settings.remediate) { + try { + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body "{`"sharingCapability`":`"$($Settings.Level)`"}" -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Set sharing level to $($Settings.level)" -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set sharing level to $($Settings.level): $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + if ($CurrentInfo.sharingCapability -eq $Settings.level) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Sharing level is set to $($Settings.level)" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Sharing level is not set to $($Settings.level)" -sev Alert + } + } + if ($Settings.report) { + Add-CIPPBPAField -FieldName 'sharingCapability' -FieldValue $CurrentInfo.sharingCapability -StoreAs string -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 new file mode 100644 index 000000000000..42261e2b2d86 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 @@ -0,0 +1,33 @@ +function Invoke-CIPPStandardunmanagedSync { + <# + .FUNCTIONALITY + Internal + #> + param($Tenant, $Settings) + If ($Settings.remediate) { + try { + $body = '{"isUnmanagedSyncAppForTenantRestricted": false}' + New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled Sync for unmanaged devices' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to disable Sync for unmanaged devices: $($_.exception.message)" -sev Error + } + } + if ($Settings.alert) { + + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + if ($CurrentInfo.isUnmanagedSyncAppForTenantRestricted -eq $false) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Sync for unmanaged devices is disabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Sync for unmanaged devices is not disabled' -sev Alert + } + } + if ($Settings.report) { + if ($CurrentInfo.isUnmanagedSyncAppForTenantRestricted -eq $false) { + $CurrentInfo.isUnmanagedSyncAppForTenantRestricted = $true + } else { + $CurrentInfo.isUnmanagedSyncAppForTenantRestricted = $false + } + Add-CIPPBPAField -FieldName 'unmanagedSync' -FieldValue [bool]$CurrentInfo.isUnmanagedSyncAppForTenantRestricted -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CippExtensions/CippExtensions.psd1 b/Modules/CippExtensions/CippExtensions.psd1 index edf5fbcddae7..437cc32f8661 100644 Binary files a/Modules/CippExtensions/CippExtensions.psd1 and b/Modules/CippExtensions/CippExtensions.psd1 differ diff --git a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDeviceWebhook.ps1 b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDeviceWebhook.ps1 index 508f96eb75b8..903cee63234c 100644 --- a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDeviceWebhook.ps1 +++ b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDeviceWebhook.ps1 @@ -42,7 +42,7 @@ function Invoke-NinjaOneDeviceWebhook { } else { - Throw "Failed to process device." + Write-LogMessage -API 'NinjaOneSync' -user 'CIPP' -message "$($DeviceM365.displayName) ($($M365DeviceID)) was not matched in Ninja for $($tenantfilter)" -Sev 'Info' } } diff --git a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDocumentTemplate.ps1 b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDocumentTemplate.ps1 index e816c66d4000..95e854007533 100644 --- a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDocumentTemplate.ps1 +++ b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneDocumentTemplate.ps1 @@ -15,8 +15,7 @@ function Invoke-NinjaOneDocumentTemplate { if (!$ID) { $DocumentTemplates = (Invoke-WebRequest -Uri "https://$($Configuration.Instance)/api/v2/document-templates/" -Method GET -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json').content | ConvertFrom-Json -Depth 100 $DocumentTemplate = $DocumentTemplates | Where-Object { $_.name -eq $Template.name } - } - else { + } else { $DocumentTemplate = (Invoke-WebRequest -Uri "https://$($Configuration.Instance)/api/v2/document-templates/$($ID)" -Method GET -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json').content | ConvertFrom-Json -Depth 100 } @@ -24,15 +23,14 @@ function Invoke-NinjaOneDocumentTemplate { if ($MatchedCount -eq 1) { # Matched a single document template $NinjaDocumentTemplate = $DocumentTemplate - } - elseif ($MatchedCount -eq 0) { + } elseif ($MatchedCount -eq 0) { # Create a new Document Template $Body = $Template | ConvertTo-Json -Depth 100 - $NinjaDocumentTemplate = (Invoke-WebRequest -Uri "https://$($Configuration.Instance)/api/v2/document-templates/" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body $Body).content | ConvertFrom-Json -Depth 100 - } - else { + Write-Host "Ninja Body: $body" + $NinjaDocumentTemplate = (Invoke-WebRequest -Uri "https://$($Configuration.Instance)/api/v2/document-templates/" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body $Body).content | ConvertFrom-Json -Depth 100 + } else { # Matched multiple templates. Should be impossible but lets check anyway :D - Throw "Multiple Documents Matched the Provided Criteria" + Throw 'Multiple Documents Matched the Provided Criteria' } return $NinjaDocumentTemplate diff --git a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneOrgMapping.ps1 b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneOrgMapping.ps1 index aba6264ff23b..0590894a8fec 100644 --- a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneOrgMapping.ps1 +++ b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneOrgMapping.ps1 @@ -102,6 +102,8 @@ function Invoke-NinjaOneOrgMapping { 'NinjaDevices' = $ParsedNinjaDevices } + Start-Sleep -Seconds 1 + } } \ No newline at end of file diff --git a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneSync.ps1 b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneSync.ps1 new file mode 100644 index 000000000000..a168d291575b --- /dev/null +++ b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneSync.ps1 @@ -0,0 +1,32 @@ +function Invoke-NinjaOneSync { + try { + $Table = Get-CIPPTable -TableName NinjaOneSettings + + $CIPPMapping = Get-CIPPTable -TableName CippMapping + $Filter = "PartitionKey eq 'NinjaOrgsMapping'" + $TenantsToProcess = Get-AzDataTableEntity @CIPPMapping -Filter $Filter | Where-Object { $Null -ne $_.NinjaOne -and $_.NinjaOne -ne '' } + + + foreach ($Tenant in $TenantsToProcess) { + Push-OutputBinding -Name NinjaProcess -Value @{ + 'NinjaAction' = 'SyncTenant' + 'MappedTenant' = $Tenant + } + Start-Sleep -Seconds 1 + } + + $AddObject = @{ + PartitionKey = 'NinjaConfig' + RowKey = 'NinjaLastRunTime' + 'SettingValue' = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') + } + + Add-AzDataTableEntity @Table -Entity $AddObject -Force + + Write-LogMessage -API 'NinjaOneAutoMap_Queue' -user 'CIPP' -message "NinjaOne Synchronization Queued for $(($TenantsToProcess | Measure-Object).count) Tenants" -Sev 'Info' + } catch { + Write-LogMessage -API 'Scheduler_Billing' -tenant 'none' -message "Could not start NinjaOne Sync $($_.Exception.Message)" -sev Error + } + +} + \ No newline at end of file diff --git a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1 b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1 index d84c6aaee35e..63e10c8043e9 100644 --- a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1 +++ b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1 @@ -4,21 +4,50 @@ function Invoke-NinjaOneTenantSync { $QueueItem ) try { + $StartQueueTime = Get-Date + Write-Host "$(Get-Date) - Starting NinjaOne Sync" + + # Stagger start + Start-Sleep -Milliseconds (Get-Random -Minimum 0 -Maximum 5001) + + # Check Global Rate Limiting + $CurrentMap = Get-ExtensionRateLimit -ExtensionName 'NinjaOne' -ExtensionPartitionKey 'NinjaOrgsMapping' -RateLimit 5 -WaitTime 60 $StartTime = Get-Date - Write-Host "$(Get-Date) - Starting NinjaOne Sync" + + # Parse out the Tenant we are processing + $MappedTenant = $QueueItem.MappedTenant + + # Check for active instances for this tenant + $CurrentItem = $CurrentMap | where-object { $_.RowKey -eq $MappedTenant.RowKey } + + $StartDate = try { Get-Date($CurrentItem.lastStartTime) } catch { $Null } + $EndDate = try { Get-Date($CurrentItem.lastEndTime) } catch { $Null } + + if (($null -ne $CurrentItem.lastStartTime) -and ($StartDate -gt (Get-Date).AddMinutes(-10)) -and ( $Null -eq $CurrentItem.lastEndTime -or ($StartDate -gt $EndDate))) { + Throw "NinjaOne Sync for Tenant $($MappedTenant.RowKey) is still running, please wait 10 minutes and try again." + } + + # Set Last Start Time + $MappingTable = Get-CIPPTable -TableName CippMapping + $CurrentItem | Add-Member -NotePropertyName lastStartTime -NotePropertyValue ([string]$(($StartQueueTime).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"))) -Force + $CurrentItem | Add-Member -NotePropertyName lastStatus -NotePropertyValue 'Running' -Force + if ($Null -ne $CurrentItem.lastEndTime -and $CurrentItem.lastEndTime -ne '' ) { + $CurrentItem.lastEndTime = ([string]$(($CurrentItem.lastEndTime).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"))) + } + Add-CIPPAzDataTableEntity @MappingTable -Entity $CurrentItem -Force + # Fetch Custom NinjaOne Settings $Table = Get-CIPPTable -TableName NinjaOneSettings - $NinjaSettings = (Get-AzDataTableEntity @Table) + $NinjaSettings = (Get-CIPPAzDataTableEntity @Table) $CIPPUrl = ($NinjaSettings | Where-Object { $_.RowKey -eq 'CIPPURL' }).SettingValue - # Parse out the Tenant we are processing - $MappedTenant = $QueueItem.MappedTenant + $Customer = Get-Tenants | where-object { $_.customerId -eq $MappedTenant.RowKey } - Write-Host "Processing: $($Customer.displayName)" + Write-Host "Processing: $($Customer.displayName) - Queued for $((New-TimeSpan -Start $StartQueueTime -End $StartTime).TotalSeconds)" - Write-LogMessage -API 'NinjaOneSync' -user 'CIPP' -message "Processing NinjaOne Synchronization for $($Customer.displayName)" -Sev 'Info' + Write-LogMessage -API 'NinjaOneSync' -user 'NinjaOneSync' -message "Processing NinjaOne Synchronization for $($Customer.displayName) - Queued for $((New-TimeSpan -Start $StartQueueTime -End $StartTime).TotalSeconds)" -Sev 'Info' if (($Customer | Measure-Object).count -ne 1) { Throw "Unable to match the recieved ID to a tenant QueueItem: $($QueueItem | ConvertTo-Json -Depth 100 | Out-String) Matched Customer: $($Customer| ConvertTo-Json -Depth 100 | Out-String)" @@ -30,13 +59,13 @@ function Invoke-NinjaOneTenantSync { # Get the NinjaOne general extension settings. $Table = Get-CIPPTable -TableName Extensionsconfig - $Configuration = ((Get-AzDataTableEntity @Table).config | ConvertFrom-Json).NinjaOne + $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).NinjaOne # Pull the list of field Mappings so we know which fields to render. $MappedFields = [pscustomobject]@{} $CIPPMapping = Get-CIPPTable -TableName CippMapping $Filter = "PartitionKey eq 'NinjaFieldMapping'" - Get-AzDataTableEntity @CIPPMapping -Filter $Filter | Where-Object { $Null -ne $_.NinjaOne -and $_.NinjaOne -ne '' } | ForEach-Object { + Get-CIPPAzDataTableEntity @CIPPMapping -Filter $Filter | Where-Object { $Null -ne $_.NinjaOne -and $_.NinjaOne -ne '' } | ForEach-Object { $MappedFields | Add-Member -NotePropertyName $_.RowKey -NotePropertyValue $($_.NinjaOne) } @@ -322,7 +351,7 @@ function Invoke-NinjaOneTenantSync { [System.Collections.Generic.List[PSCustomObject]]$SecureScoreProfiles = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'SecureScoreControlProfiles' - $CurrentSecureScore = ($SecureScore | Sort-Object createDateTiime -Descending)[0] + $CurrentSecureScore = ($SecureScore | Sort-Object createDateTime -Descending | Select-Object -First 1) $MaxSecureScoreRank = ($SecureScoreProfiles.rank | Measure-Object -Maximum).maximum $MaxSecureScore = $CurrentSecureScore.maxScore @@ -841,7 +870,7 @@ function Invoke-NinjaOneTenantSync { # Update Device if ($MappedFields.DeviceSummary -or $MappedFields.DeviceLinks -or $MappedFields.DeviceCompliance) { - $Result = Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/device/$($MatchedNinjaDevice.id)/custom-fields" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ($NinjaDeviceUpdate | ConvertTo-Json -Depth 100) + $Result = Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/device/$($MatchedNinjaDevice.id)/custom-fields" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ($NinjaDeviceUpdate | ConvertTo-Json -Depth 100) } } @@ -1037,13 +1066,13 @@ function Invoke-NinjaOneTenantSync { $OneDriveUseColor = if ($OneDriveUse.Percent -ge 95) { '#D53948' - } elseif ($MailboxUse.Percent -ge 85) { + } elseif ($OneDriveUse.Percent -ge 85) { '#FFA500' } else { '#26A644' } - $OneDriveParsed = '
' + $OneDriveParsed = '
' } else { $OneDriveUse = [PSCustomObject]@{ @@ -1097,7 +1126,7 @@ function Invoke-NinjaOneTenantSync { '#26A644' } - $MailboxParsed = '
' + $MailboxParsed = '
' } else { $MailboxUse = [PSCustomObject]@{ @@ -1327,7 +1356,7 @@ function Invoke-NinjaOneTenantSync { # Create New Users if (($NinjaUserCreation | Measure-Object).count -ge 100) { Write-Host "Creating NinjaOne Users" - $CreatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ("[$($NinjaUserCreation.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 + [System.Collections.Generic.List[PSCustomObject]]$CreatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ("[$($NinjaUserCreation.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 Remove-AzDataTableEntity @UsersUpdateTable -Entity $NinjaUserCreation [System.Collections.Generic.List[PSCustomObject]]$NinjaUserCreation = @() } @@ -1339,7 +1368,7 @@ function Invoke-NinjaOneTenantSync { # Update Users if (($NinjaUserUpdates | Measure-Object).count -ge 100) { Write-Host "Updating NinjaOne Users" - $UpdatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ("[$($NinjaUserUpdates.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 + [System.Collections.Generic.List[PSCustomObject]]$UpdatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ("[$($NinjaUserUpdates.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 Remove-AzDataTableEntity @UsersUpdateTable -Entity $NinjaUserUpdates [System.Collections.Generic.List[PSCustomObject]]$NinjaUserUpdates = @() } @@ -1348,7 +1377,7 @@ function Invoke-NinjaOneTenantSync { } - $UserDocResults = $UpdatedUsers + $CreatedUsers + [System.Collections.Generic.List[PSCustomObject]]$UserDocResults = $UpdatedUsers + $CreatedUsers if (($UserDocResults | Where-Object { $Null -ne $_ -and $_ -ne '' } | Measure-Object).count -ge 1) { $UserDocResults | Where-Object { $Null -ne $_ -and $_ -ne '' } | ForEach-Object { @@ -1402,7 +1431,7 @@ function Invoke-NinjaOneTenantSync { # Create New Users if (($NinjaUserCreation | Measure-Object).count -ge 1) { Write-Host "Creating NinjaOne Users" - $CreatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ("[$($NinjaUserCreation.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 + [System.Collections.Generic.List[PSCustomObject]]$CreatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ("[$($NinjaUserCreation.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 Remove-AzDataTableEntity @UsersUpdateTable -Entity $NinjaUserCreation } @@ -1414,7 +1443,7 @@ function Invoke-NinjaOneTenantSync { # Update Users if (($NinjaUserUpdates | Measure-Object).count -ge 1) { Write-Host "Updating NinjaOne Users" - $UpdatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ("[$($NinjaUserUpdates.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 + [System.Collections.Generic.List[PSCustomObject]]$UpdatedUsers = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ("[$($NinjaUserUpdates.body -join ',')]") -EA Stop).content | ConvertFrom-Json -Depth 100 Remove-AzDataTableEntity @UsersUpdateTable -Entity $NinjaUserUpdates } } Catch { @@ -1425,7 +1454,7 @@ function Invoke-NinjaOneTenantSync { # Parse out the NinjaOne ID to MS ID - $UserDocResults = $UpdatedUsers + $CreatedUsers + [System.Collections.Generic.List[PSCustomObject]]$UserDocResults = $UpdatedUsers + $CreatedUsers if (($UserDocResults | Where-Object { $Null -ne $_ -and $_ -ne '' } | Measure-Object).count -ge 1) { $UserDocResults | Where-Object { $Null -ne $_ -and $_ -ne '' } | ForEach-Object { @@ -1598,7 +1627,7 @@ function Invoke-NinjaOneTenantSync { # Create New Subscriptions if (($NinjaLicenseCreation | Measure-Object).count -ge 1) { Write-Host "Creating NinjaOne Licenses" - $CreatedLicenses = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ($NinjaLicenseCreation | ConvertTo-Json -Depth 100 -AsArray) -EA Stop).content | ConvertFrom-Json -Depth 100 + [System.Collections.Generic.List[PSCustomObject]]$CreatedLicenses = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method POST -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ($NinjaLicenseCreation | ConvertTo-Json -Depth 100 -AsArray) -EA Stop).content | ConvertFrom-Json -Depth 100 } } Catch { Write-Host "Bulk Creation Error, but may have been successful as only 1 record with an issue could have been the cause: $_" @@ -1608,14 +1637,14 @@ function Invoke-NinjaOneTenantSync { # Update Subscriptions if (($NinjaLicenseUpdates | Measure-Object).count -ge 1) { Write-Host "Updating NinjaOne Licenses" - $UpdatedLicenses = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ($NinjaLicenseUpdates | ConvertTo-Json -Depth 100 -AsArray) -EA Stop).content | ConvertFrom-Json -Depth 100 + [System.Collections.Generic.List[PSCustomObject]]$UpdatedLicenses = (Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/documents" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ($NinjaLicenseUpdates | ConvertTo-Json -Depth 100 -AsArray) -EA Stop).content | ConvertFrom-Json -Depth 100 Write-Host "Completed Update" } } Catch { Write-Host "Bulk Update Errored, but may have been successful as only 1 record with an issue could have been the cause: $_" } - $LicenseDocs = $CreatedLicenses + $UpdatedLicenses + [System.Collections.Generic.List[PSCustomObject]]$LicenseDocs = $CreatedLicenses + $UpdatedLicenses if ($Configuration.LicenseDocumentsEnabled -eq $True -and $Configuration.UserDocumentsEnabled -eq $True) { # Relate Subscriptions to Users @@ -1943,12 +1972,12 @@ function Invoke-NinjaOneTenantSync { }, @{ Label = 'Points to Obtain' - Amount = $MaxSecureScoreRank - $CurrentSecureScore.currentScore + Amount = $MaxSecureScore - $CurrentSecureScore.currentScore Colour = '#CCCCCC' } ) - $SecureScoreHTML = Get-NinjaInLineBarGraph -Title "Secure Score - $([System.Math]::Round((($CurrentSecureScore.currentScore / $MaxSecureScoreRank) * 100),2))%" -Data $Data -KeyInLine -NoCount -NoSort + $SecureScoreHTML = Get-NinjaInLineBarGraph -Title "Secure Score - $([System.Math]::Round((($CurrentSecureScore.currentScore / $MaxSecureScore) * 100),2))%" -Data $Data -KeyInLine -NoCount -NoSort # Recommended Actions HTML $RecommendedActionsHTML = $Top5Actions | Select-Object 'Recommended Action', @{n = 'Score Impact'; e = { "+$($_.'Score Impact')%" } }, Category, @{n = 'Link'; e = { '' } } | ConvertTo-Html -As Table -Fragment @@ -1963,13 +1992,14 @@ function Invoke-NinjaOneTenantSync { ### CIPP Applied Standards Cards Write-Host "Applied Standards" + Set-Location (Get-Item $PSScriptRoot).Parent.Parent.Parent.FullName $StandardsDefinitions = Get-Content 'config/standards.json' | ConvertFrom-Json -Depth 100 $Table = Get-CippTable -tablename 'standards' $Filter = "PartitionKey eq 'standards'" - $AllStandards = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json -Depth 100 + $AllStandards = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json -Depth 100 $AppliedStandards = ($AllStandards | Where-Object { $_.Tenant -eq $Customer.defaultDomainName -or $_.Tenant -eq 'AllTenants' }) @@ -1996,7 +2026,7 @@ function Invoke-NinjaOneTenantSync { ### License Card Write-Host "License Details" $LicenseTableHTML = $LicensesParsed | Sort-Object 'License Name' | ConvertTo-HTML -As Table -Fragment - $LicenseTableHTML = ([System.Web.HttpUtility]::HtmlDecode($LicenseTableHTML) -replace '', '') -replace '', '' + $LicenseTableHTML = '
' + (([System.Web.HttpUtility]::HtmlDecode($LicenseTableHTML) -replace '', '') -replace '', '') + '
' $TitleLink = "https://$CIPPUrl/tenant/administration/list-licenses?customerId=$($Customer.customerId)" $LicensesSummaryCardHTML = Get-NinjaOneCard -Title 'Licenses' -Body $LicenseTableHTML -Icon 'fas fa-chart-bar' -TitleLink $TitleLink @@ -2249,8 +2279,9 @@ function Invoke-NinjaOneTenantSync { $Token = Get-NinjaOneToken -configuration $Configuration - - $Result = Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/$($MappedTenant.NinjaOne)/custom-fields" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json' -Body ($NinjaOrgUpdate | ConvertTo-Json -Depth 100) + Write-Host "Ninja Body: $($NinjaOrgUpdate | ConvertTo-Json -Depth 100)" + $Result = Invoke-WebRequest -uri "https://$($Configuration.Instance)/api/v2/organization/$($MappedTenant.NinjaOne)/custom-fields" -Method PATCH -Headers @{Authorization = "Bearer $($token.access_token)" } -ContentType 'application/json; charset=utf-8' -Body ($NinjaOrgUpdate | ConvertTo-Json -Depth 100) + Write-Host "Cleaning Users Cache" if (($ParsedUsers | Measure-Object).count -gt 0) { @@ -2264,10 +2295,19 @@ function Invoke-NinjaOneTenantSync { Write-Host "Total Fetch Time: $((New-TimeSpan -Start $StartTime -End $FetchEnd).TotalSeconds)" Write-Host "Completed Total Time: $((New-TimeSpan -Start $StartTime -End (Get-Date)).TotalSeconds)" - Write-LogMessage -API 'NinjaOneSync' -user 'CIPP' -message "Completed NinjaOne Sync for $($Customer.displayName). Data fetched in $((New-TimeSpan -Start $StartTime -End $FetchEnd).TotalSeconds) seconds. Total time $((New-TimeSpan -Start $StartTime -End (Get-Date)).TotalSeconds) seconds" -Sev 'info' + + # Set Last End Time + $CurrentItem | Add-Member -NotePropertyName lastEndTime -NotePropertyValue ([string]$((Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"))) -Force + $CurrentItem | Add-Member -NotePropertyName lastStatus -NotePropertyValue 'Completed' -Force + Add-CIPPAzDataTableEntity @MappingTable -Entity $CurrentItem -Force + + Write-LogMessage -API 'NinjaOneSync' -user 'NinjaOneSync' -message "Completed NinjaOne Sync for $($Customer.displayName). Queued for $((New-TimeSpan -Start $StartQueueTime -End $StartTime).TotalSeconds) seconds. Data fetched in $((New-TimeSpan -Start $StartTime -End $FetchEnd).TotalSeconds) seconds. Total processing time $((New-TimeSpan -Start $StartTime -End (Get-Date)).TotalSeconds) seconds" -Sev 'info' } catch { Write-Error "Failed NinjaOne Processing for $($Customer.displayName) Linenumber: $($_.InvocationInfo.ScriptLineNumber) Error: $($_.Exception.message)" - Write-LogMessage -API 'NinjaOneSync' -user 'CIPP' -message "Failed NinjaOne Processing for $($Customer.displayName) Linenumber: $($_.InvocationInfo.ScriptLineNumber) Error: $($_.Exception.message)" -Sev 'Error' + Write-LogMessage -API 'NinjaOneSync' -user 'NinjaOneSync' -message "Failed NinjaOne Processing for $($Customer.displayName) Linenumber: $($_.InvocationInfo.ScriptLineNumber) Error: $($_.Exception.message)" -Sev 'Error' + $CurrentItem | Add-Member -NotePropertyName lastEndTime -NotePropertyValue ([string]$((Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"))) -Force + $CurrentItem | Add-Member -NotePropertyName lastStatus -NotePropertyValue 'Failed' -Force + Add-CIPPAzDataTableEntity @MappingTable -Entity $CurrentItem -Force } -} \ No newline at end of file +} diff --git a/Modules/CippExtensions/Public/Get-ExtensionRateLimit.ps1 b/Modules/CippExtensions/Public/Get-ExtensionRateLimit.ps1 new file mode 100644 index 000000000000..069dec362229 --- /dev/null +++ b/Modules/CippExtensions/Public/Get-ExtensionRateLimit.ps1 @@ -0,0 +1,33 @@ +function Get-ExtensionRateLimit($ExtensionName, $ExtensionPartitionKey, $RateLimit, $WaitTime) { + + $MappingTable = Get-CIPPTable -TableName CippMapping + $CurrentMap = (Get-CIPPAzDataTableEntity @MappingTable -Filter "PartitionKey eq '$ExtensionPartitionKey'") + $CurrentMap | ForEach-Object { + if ($Null -ne $_.lastEndTime -and $_.lastEndTime -ne ''){ + $_.lastEndTime = (Get-Date($_.lastEndTime)) + } else { + $_ | Add-Member -NotePropertyName lastEndTime -NotePropertyValue $Null -Force + } + + if ($Null -ne $_.lastStartTime -and $_.lastStartTime -ne '') { + $_.lastStartTime = (Get-Date($_.lastStartTime)) + } else { + $_ | Add-Member -NotePropertyName lastStartTime -NotePropertyValue $Null -Force + } + } + + # Check Global Rate Limiting + try { + $ActiveJobs = $CurrentMap | Where-Object { ($Null -ne $_.lastStartTime) -and ($_.lastStartTime -gt (Get-Date).AddMinutes(-10)) -and ($Null -eq $_.lastEndTime -or $_.lastStartTime -gt $_.lastEndTime) } + } catch { + $ActiveJobs = 'FirstRun' + } + if (($ActiveJobs | Measure-Object).count -ge $RateLimit) { + Write-Host "Rate Limiting. Currently $($ActiveJobs.count) Active Jobs" + Start-Sleep -Seconds $WaitTime + $CurrentMap = Get-ExtensionRateLimit -ExtensionName $ExtensionName -ExtensionPartitionKey $ExtensionPartitionKey -RateLimit $RateLimit -WaitTime $WaitTime + } + + Return $CurrentMap + +} \ No newline at end of file diff --git a/Scheduler_Extensions/run.ps1 b/Scheduler_Extensions/run.ps1 index b8d80be6a5bf..c6ce09744cbd 100644 --- a/Scheduler_Extensions/run.ps1 +++ b/Scheduler_Extensions/run.ps1 @@ -15,7 +15,6 @@ if ($Configuration.NinjaOne.Enabled -eq $True) { $Settings = (Get-AzDataTableEntity @Table) $TimeSetting = ($Settings | Where-Object { $_.RowKey -eq 'NinjaSyncTime' }).SettingValue - if (($TimeSetting | Measure-Object).count -ne 1) { [int]$TimeSetting = Get-Random -Minimum 1 -Maximum 95 @@ -38,17 +37,18 @@ if ($Configuration.NinjaOne.Enabled -eq $True) { Write-Host "Current Interval: $CurrentInterval" + $CIPPMapping = Get-CIPPTable -TableName CippMapping + $Filter = "PartitionKey eq 'NinjaOrgsMapping'" + $TenantsToProcess = Get-AzDataTableEntity @CIPPMapping -Filter $Filter | Where-Object { $Null -ne $_.NinjaOne -and $_.NinjaOne -ne '' } + if ($Null -eq $LastRunTime -or $LastRunTime -le (Get-Date).addhours(-25) -or $TimeSetting -eq $CurrentInterval) { Write-Host "Executing" - $CIPPMapping = Get-CIPPTable -TableName CippMapping - $Filter = "PartitionKey eq 'NinjaOrgsMapping'" - $TenantsToProcess = Get-AzDataTableEntity @CIPPMapping -Filter $Filter | Where-Object { $Null -ne $_.NinjaOne -and $_.NinjaOne -ne '' } - - foreach ($Tenant in $TenantsToProcess) { + foreach ($Tenant in $TenantsToProcess | Sort-Object lastEndTime) { Push-OutputBinding -Name NinjaProcess -Value @{ 'NinjaAction' = 'SyncTenant' 'MappedTenant' = $Tenant } + Start-Sleep -Seconds 1 } @@ -59,7 +59,36 @@ if ($Configuration.NinjaOne.Enabled -eq $True) { } Add-AzDataTableEntity @Table -Entity $AddObject -Force - Write-LogMessage -API 'NinjaOneAutoMap_Queue' -user 'CIPP' -message "NinjaOne Synchronization Queued for $(($TenantsToProcess | Measure-Object).count) Tenants" -Sev 'Info' + Write-LogMessage -API 'NinjaOneSync' -user 'CIPP' -message "NinjaOne Daily Synchronization Queued for $(($TenantsToProcess | Measure-Object).count) Tenants" -Sev 'Info' + + } else { + if ($LastRunTime -lt (Get-Date).AddMinutes(-90)) { + $TenantsToProcess | ForEach-Object { + if ($Null -ne $_.lastEndTime -and $_.lastEndTime -ne '') { + $_.lastEndTime = (Get-Date($_.lastEndTime)) + } else { + $_ | Add-Member -NotePropertyName lastEndTime -NotePropertyValue $Null -Force + } + + if ($Null -ne $_.lastStartTime -and $_.lastStartTime -ne '') { + $_.lastStartTime = (Get-Date($_.lastStartTime)) + } else { + $_ | Add-Member -NotePropertyName lastStartTime -NotePropertyValue $Null -Force + } + } + $CatchupTenants = $TenantsToProcess | where-object { (((($_.lastEndTime -eq $Null) -or ($_.lastStartTime -gt $_.lastEndTime)) -and ($_.lastStartTime -lt (Get-Date).AddMinutes(-30)))) -or ($_.lastStartTime -lt $LastRunTime) } + foreach ($Tenant in $CatchupTenants) { + Push-OutputBinding -Name NinjaProcess -Value @{ + 'NinjaAction' = 'SyncTenant' + 'MappedTenant' = $Tenant + } + Start-Sleep -Seconds 1 + } + if (($CatchupTenants | Measure-Object).count -gt 0){ + Write-LogMessage -API 'NinjaOneSync' -user 'CIPP' -message "NinjaOne Synchronization Catchup Queued for $(($CatchupTenants | Measure-Object).count) Tenants" -Sev 'Info' + } + + } } } \ No newline at end of file diff --git a/Scheduler_RenewGraphSubscriptions/function.json b/Scheduler_RenewGraphSubscriptions/function.json index d2e7f34face4..114e4c0f7aab 100644 --- a/Scheduler_RenewGraphSubscriptions/function.json +++ b/Scheduler_RenewGraphSubscriptions/function.json @@ -4,7 +4,7 @@ "name": "Timer", "type": "timerTrigger", "direction": "in", - "schedule": "0 0 0 * * *" + "schedule": "0 10 * * * *" } ] } diff --git a/Standards_OrchestrationStarterTimer/function.json b/Scheduler_Standards/function.json similarity index 58% rename from Standards_OrchestrationStarterTimer/function.json rename to Scheduler_Standards/function.json index 0860d6f56788..88d7d049eb48 100644 --- a/Standards_OrchestrationStarterTimer/function.json +++ b/Scheduler_Standards/function.json @@ -7,9 +7,10 @@ "type": "timerTrigger" }, { - "name": "starter", - "type": "durableClient", - "direction": "in" + "type": "queue", + "direction": "out", + "name": "QueueItem", + "queueName": "CIPPGenericQueue" } ] -} \ No newline at end of file +} diff --git a/Scheduler_Standards/run.ps1 b/Scheduler_Standards/run.ps1 new file mode 100644 index 000000000000..7466a60f5338 --- /dev/null +++ b/Scheduler_Standards/run.ps1 @@ -0,0 +1,6 @@ +using namespace System.Net + +param($Timer) +Write-LogMessage -API 'Standards' -message 'Starting Standards Schedule' -sev Info +Invoke-CIPPStandardsRun -tenantfilter 'allTenants' +Write-LogMessage -API 'Standards' -message 'Launched all standard jobs' -sev Info \ No newline at end of file diff --git a/Standards_ActivityBasedTimeout/function.json b/Standards_ActivityBasedTimeout/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_ActivityBasedTimeout/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_ActivityBasedTimeout/run.ps1 b/Standards_ActivityBasedTimeout/run.ps1 deleted file mode 100644 index 158fa444936d..000000000000 --- a/Standards_ActivityBasedTimeout/run.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -param($tenant) -try { - $State = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies" -tenantid $tenant).id - if (!$State) { - $body = @" -{ - "displayName": "DefaultTimeoutPolicy", - "isOrganizationDefault": true, - "definition":["{\"ActivityBasedTimeoutPolicy\":{\"Version\":1,\"ApplicationPolicies\":[{\"ApplicationId\":\"default\",\"WebSessionIdleTimeout\":\"01:00:00\"}]}}"] -} -"@ - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies" -Type POST -Body $body -ContentType "application/json") - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled Activity Based Timeout of one hour" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable Activity Based Timeout $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_AddDKIM/function.json b/Standards_AddDKIM/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_AddDKIM/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_AddDKIM/run.ps1 b/Standards_AddDKIM/run.ps1 deleted file mode 100644 index ec4ec1a841de..000000000000 --- a/Standards_AddDKIM/run.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -param($tenant) - -try { - $DKIM = (New-ExoRequest -tenantid $tenant -cmdlet "Get-DkimSigningConfig") | Where-Object -Property Enabled -EQ $false | ForEach-Object { - (New-ExoRequest -tenantid $tenant -cmdlet "New-DkimSigningConfig" -cmdparams @{ KeySize = 2048; DomainName = $_.Identity; Enabled = $true } -useSystemMailbox $true) - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled DKIM Setup" -sev Info - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable DKIM. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_AnonReportDisable/function.json b/Standards_AnonReportDisable/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_AnonReportDisable/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_AnonReportDisable/run.ps1 b/Standards_AnonReportDisable/run.ps1 deleted file mode 100644 index c04f87b957d3..000000000000 --- a/Standards_AnonReportDisable/run.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -param($tenant) - -try { - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/reportSettings" -Type patch -Body '{"displayConcealedNames": false}' -ContentType "application/json" -AsApp $true - Write-LogMessage -API "Standards" -tenant $tenant -message "Anonymous Reports Disabled." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable anonymous reports. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_AuditLog/function.json b/Standards_AuditLog/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_AuditLog/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_AuditLog/run.ps1 b/Standards_AuditLog/run.ps1 deleted file mode 100644 index b4f77d268247..000000000000 --- a/Standards_AuditLog/run.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -param($tenant) - -$DehydratedTenant = (New-ExoRequest -tenantid $Tenant -cmdlet "Get-OrganizationConfig").IsDehydrated -if ($DehydratedTenant) { - New-ExoRequest -tenantid $Tenant -cmdlet "Enable-OrganizationCustomization" -} - -try { - - $AuditLogEnabled = (New-ExoRequest -tenantid $Tenant -cmdlet "Get-AdminAuditLogConfig").UnifiedAuditLogIngestionEnabled - if ($AuditLogEnabled) { - Write-LogMessage -API "Standards" -tenant $tenant -message "Unified Audit Log already enabled." -sev Info - } - else { - $AdminAuditLogParams = @{ - UnifiedAuditLogIngestionEnabled = $true - } - New-ExoRequest -tenantid $Tenant -cmdlet "Set-AdminAuditLogConfig" -cmdParams $AdminAuditLogParams - Write-LogMessage -API "Standards" -tenant $tenant -message "Unified Audit Log Enabled." -sev Info - } - -} -catch { - - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to apply Unified Audit Log. Error: $ErrorMessage" -sev Error -} \ No newline at end of file diff --git a/Standards_AutoExpandArchive/function.json b/Standards_AutoExpandArchive/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_AutoExpandArchive/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_AutoExpandArchive/run.ps1 b/Standards_AutoExpandArchive/run.ps1 deleted file mode 100644 index 2f7232f981d7..000000000000 --- a/Standards_AutoExpandArchive/run.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -param($tenant) - -try { - - $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet "Get-OrganizationConfig").AutoExpandingArchiveEnabled - if (!$currentstate) { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-OrganizationConfig" -cmdParams @{AutoExpandingArchive = $true } - Write-LogMessage -API "Standards" -tenant $tenant -message "Added Auto Expanding Archive." -sev Info - } - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to apply Auto Expanding Archives Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_AzurePortal/function.json b/Standards_AzurePortal/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_AzurePortal/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_AzurePortal/run.ps1 b/Standards_AzurePortal/run.ps1 deleted file mode 100644 index d047e8c27ae1..000000000000 --- a/Standards_AzurePortal/run.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -param($tenant) - -Write-LogMessage -API "Standards" -tenant $tenant -message "Azure Portal disablement is no longer functional. Please remove this standard." -sev Error diff --git a/Standards_ConditionalAccess/function.json b/Standards_ConditionalAccess/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_ConditionalAccess/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_ConditionalAccess/run.ps1 b/Standards_ConditionalAccess/run.ps1 deleted file mode 100644 index 0730b41371da..000000000000 --- a/Standards_ConditionalAccess/run.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.ConditionalAccess -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.ConditionalAccess -} - -$APINAME = "Standards" - -foreach ($Template in $Setting.TemplateList) { - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$($Template.value)'" - $JSONObj = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON - $CAPolicy = New-CIPPCAPolicy -TenantFilter $tenant -state $request.body.NewState -RawJSON $JSONObj -Overwrite $true -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to create or update conditional access rule $($JSONObj.displayName): $($_.exception.message)" -sev "Error" - } -} - - diff --git a/Standards_DelegateSentItems/function.json b/Standards_DelegateSentItems/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DelegateSentItems/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DelegateSentItems/run.ps1 b/Standards_DelegateSentItems/run.ps1 deleted file mode 100644 index 55dcb4b3b023..000000000000 --- a/Standards_DelegateSentItems/run.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -param($tenant) - -try { - $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet "Get-Mailbox" -cmdParams @{ RecipientTypeDetails = @("UserMailbox", "SharedMailbox") } | Where-Object { $_.MessageCopyForSendOnBehalfEnabled -eq $false -or $_.MessageCopyForSentAsEnabled -eq $false } | ForEach-Object { - try { - $username = $_.UserPrincipalName - New-ExoRequest -tenantid $Tenant -cmdlet "set-mailbox" -cmdParams @{Identity = $_.GUID ; MessageCopyForSendOnBehalfEnabled = $True; MessageCopyForSentAsEnabled = $True } -anchor $username - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not enable delegate sent item style for $($username): $($_.Exception.message)" -sev Warn - } - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Delegate Sent Items Style enabled." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to apply Delegate Sent Items Style. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DeletedUserRentention/function.json b/Standards_DeletedUserRentention/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_DeletedUserRentention/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_DeletedUserRentention/run.ps1 b/Standards_DeletedUserRentention/run.ps1 deleted file mode 100644 index e4b6e31f2842..000000000000 --- a/Standards_DeletedUserRentention/run.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -param($tenant) - -try { - $body = '{"deletedUserPersonalSiteRetentionPeriodInDays": 365}' - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/sharepoint/settings" -AsApp $true -Type PATCH -Body $body -ContentType "application/json" - - Write-LogMessage -API "Standards" -tenant $tenant -message "Set deleted user rentention of OneDrive to 1 year" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set deleted user rentention of OneDrive to 1 year: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DisableAddShortcutsToOneDrive/function.json b/Standards_DisableAddShortcutsToOneDrive/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_DisableAddShortcutsToOneDrive/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableAddShortcutsToOneDrive/run.ps1 b/Standards_DisableAddShortcutsToOneDrive/run.ps1 deleted file mode 100644 index 65c215683680..000000000000 --- a/Standards_DisableAddShortcutsToOneDrive/run.ps1 +++ /dev/null @@ -1,89 +0,0 @@ -param($tenant) - -function GetTenantRequestXml { - return @" - - - - - - - - - - - - - -"@ -} - -function GetDisableAddShortcutsToOneDriveXml { - param( - [string]$identity - ) - - # the json object gives us a space and a newline :( - $identity = $identity.Replace(" ", "") - $identity = $identity.Replace("`n", " ") - return @" - - - - true - - - - - - -"@ -} - -$log = @{ - API = "Standards" - tenant = $tenant - message = "" - sev = "Info" -} - -try { - $OnMicrosoft = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains?$top=999' -tenantid $tenant | - Where-Object -Property isInitial -EQ $true).id.split('.') | Select-Object -First 1 - $AdminUrl = "https://$($OnMicrosoft)-admin.sharepoint.com" - $graphRequest = @{ - "scope" = "$AdminURL/.default" - "tenantid" = $tenant - "uri" = "$AdminURL/_vti_bin/client.svc/ProcessQuery" - "type" = "POST" - "body" = GetTenantRequestXml - "ContentType" = "text/xml" - } - - $response = New-GraphPostRequest @graphRequest - if (!$response.ErrorInfo.ErrorMessage) { - $log.message = "Received Tenant from Sharepoint" - Write-LogMessage @log - } - - $graphRequest.Body = GetDisableAddShortcutsToOneDriveXml -identity $response._ObjectIdentity_ - $response = New-GraphPostRequest @graphRequest - - if (!$response.ErrorInfo.ErrorMessage) { - $log.message = "Set DisableAddShortcutsToOneDrive to True on $tenant" - } - else { - $log.message = "Unable to set DisableAddShortcutsToOneDrive to True ` - on $($tenant): $($response.ErrorInfo.ErrorMessage)" - } -} -catch { - $log.message = "Failed to set OneDrive shortcut: $($_.Exception.Message)" - $log.sev = "Error" -} - -Write-LogMessage @log \ No newline at end of file diff --git a/Standards_DisableBasicAuth/function.json b/Standards_DisableBasicAuth/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableBasicAuth/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableBasicAuth/run.ps1 b/Standards_DisableBasicAuth/run.ps1 deleted file mode 100644 index beab79e449d7..000000000000 --- a/Standards_DisableBasicAuth/run.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -param($tenant) -Write-LogMessage -API "Standards" -tenant $tenant -message "Basic Authentication is disabled by default. SMTP authentication is still allowed. Please use the standard 'Disable SMTP Basic Authentication' to disable" -sev Info diff --git a/Standards_DisableBasicAuthSMTP/function.json b/Standards_DisableBasicAuthSMTP/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableBasicAuthSMTP/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableBasicAuthSMTP/run.ps1 b/Standards_DisableBasicAuthSMTP/run.ps1 deleted file mode 100644 index 8bef6658e5cd..000000000000 --- a/Standards_DisableBasicAuthSMTP/run.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -param($tenant) - -try { - $Request = New-ExoRequest -tenantid $Tenant -cmdlet "Set-TransportConfig" -cmdParams @{ SmtpClientAuthenticationDisabled = $true } - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled SMTP Basic Authentication" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable SMTP Basic Authentication: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DisableGuestDirectory/function.json b/Standards_DisableGuestDirectory/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableGuestDirectory/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableGuestDirectory/run.ps1 b/Standards_DisableGuestDirectory/run.ps1 deleted file mode 100644 index cc81ded587a3..000000000000 --- a/Standards_DisableGuestDirectory/run.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -param($tenant) - -try { - $body = '{guestUserRoleId: "2af84b1e-32c8-42b7-82bc-daa82404023b"}' - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -Type patch -Body $body -ContentType "application/json") - - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled Guest access to directory information." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable Guest access to directory information.: $($_.exception.message)" -sev "Error" -} diff --git a/Standards_DisableGuests/function.json b/Standards_DisableGuests/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_DisableGuests/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableGuests/run.ps1 b/Standards_DisableGuests/run.ps1 deleted file mode 100644 index abf43e7bfb11..000000000000 --- a/Standards_DisableGuests/run.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -param($tenant) - -try { - $lookup = (Get-Date).AddDays(-90).ToUniversalTime().ToString('o') - $GraphRequest = New-GraphgetRequest -uri "https://graph.microsoft.com/beta/users?`$filter=(signInActivity/lastSignInDateTime le $lookup)&`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled" -scope "https://graph.microsoft.com/.default" -tenantid $Tenant | Where-Object { $_.userType -EQ 'Guest' -and $_.AccountEnabled -EQ $true } - foreach ($guest in $GraphRequest) { - New-GraphPostRequest -type Patch -tenantid $tenant -uri "https://graph.microsoft.com/beta/users/$($guest.id)" -body '{"accountEnabled":"false"}' - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabling guest $($guest.UserPrincipalName) ($($guest.id))" -sev Info - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled guests accounts with a login longer than 90 days ago." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable guests older than 90 days: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DisableM365GroupUsers/function.json b/Standards_DisableM365GroupUsers/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableM365GroupUsers/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableM365GroupUsers/run.ps1 b/Standards_DisableM365GroupUsers/run.ps1 deleted file mode 100644 index 54dc6199d3fa..000000000000 --- a/Standards_DisableM365GroupUsers/run.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -param($tenant) - -try { - $CurrentState = (New-GraphGetRequest -asApp $true -Uri "https://graph.microsoft.com/beta/settings" -tenantid $tenant) | Where-Object -Property displayname -EQ 'Group.unified' - if (!$CurrentState) { - #if no current configuration is found, we set it to the default template supplied by MS. - $CurrentState = '{"id":"","displayName":"Group.Unified","templateId":"62375ab9-6b52-47ed-826b-58e47e0e304b","values":[{"name":"NewUnifiedGroupWritebackDefault","value":"true"},{"name":"EnableMIPLabels","value":"false"},{"name":"CustomBlockedWordsList","value":""},{"name":"EnableMSStandardBlockedWords","value":"false"},{"name":"ClassificationDescriptions","value":""},{"name":"DefaultClassification","value":""},{"name":"PrefixSuffixNamingRequirement","value":""},{"name":"AllowGuestsToBeGroupOwner","value":"false"},{"name":"AllowGuestsToAccessGroups","value":"true"},{"name":"GuestUsageGuidelinesUrl","value":""},{"name":"GroupCreationAllowedGroupId","value":""},{"name":"AllowToAddGuests","value":"true"},{"name":"UsageGuidelinesUrl","value":""},{"name":"ClassificationList","value":""},{"name":"EnableGroupCreation","value":"true"}]}' - (New-GraphPostRequest -AsApp $true -tenantid $tenant -Uri "https://graph.microsoft.com/beta/settings/$($CurrentState.id)" -Type POST -Body $CurrentState -ContentType "application/json") - $CurrentState = (New-GraphGetRequest -asApp $true -Uri "https://graph.microsoft.com/beta/settings" -tenantid $tenant) | Where-Object -Property displayname -EQ 'Group.unified' - } - ($CurrentState.values | Where-Object { $_.name -eq 'EnableGroupCreation' }).value = "false" - $body = "{values : $($CurrentState.values | ConvertTo-Json -Compress)}" - (New-GraphPostRequest -AsApp $true -tenantid $tenant -Uri "https://graph.microsoft.com/beta/settings/$($CurrentState.id)" -Type patch -Body $body -ContentType "application/json") - Write-LogMessage -API "Standards" -tenant $tenant -message "Standards API: Disabled users from creating M365 Groups." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable users from creating M365 Groups: $($_.exception.message)" -sev "Error" -} diff --git a/Standards_DisableReshare/function.json b/Standards_DisableReshare/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_DisableReshare/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableReshare/run.ps1 b/Standards_DisableReshare/run.ps1 deleted file mode 100644 index c1757dee151f..000000000000 --- a/Standards_DisableReshare/run.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -param($tenant) - -try { - $body = '{"isResharingByExternalUsersEnabled": "False"}' - $Request = New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/sharepoint/settings" -AsApp $true -Type patch -Body $body -ContentType "application/json" - Write-Host ($Request | ConvertTo-Json) - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled guests from resharing files" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable guests from resharing files: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DisableSecurityGroupUsers/function.json b/Standards_DisableSecurityGroupUsers/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableSecurityGroupUsers/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableSecurityGroupUsers/run.ps1 b/Standards_DisableSecurityGroupUsers/run.ps1 deleted file mode 100644 index 459c82c2d72a..000000000000 --- a/Standards_DisableSecurityGroupUsers/run.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -param($tenant) - -try { - $body = '{"defaultUserRolePermissions":{"allowedToCreateSecurityGroups":false}}' - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -Type patch -Body $body -ContentType "application/json") - - Write-LogMessage -API "Standards" -tenant $tenant -message "Standards API: Disabled users from creating Security Groups." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable users from creating Security Groups: $($_.exception.message)" -sev "Error" -} diff --git a/Standards_DisableSelfServiceLicenses/function.json b/Standards_DisableSelfServiceLicenses/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableSelfServiceLicenses/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableSelfServiceLicenses/run.ps1 b/Standards_DisableSelfServiceLicenses/run.ps1 deleted file mode 100644 index 3a6960cdd678..000000000000 --- a/Standards_DisableSelfServiceLicenses/run.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -param($tenant) - -try { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable License Buy Self Service: $($_.exception.message)" -sev Error - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable License Buy Self Service: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DisableSharedMailbox/function.json b/Standards_DisableSharedMailbox/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableSharedMailbox/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableSharedMailbox/run.ps1 b/Standards_DisableSharedMailbox/run.ps1 deleted file mode 100644 index 9b4d6083270a..000000000000 --- a/Standards_DisableSharedMailbox/run.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -param($tenant) - -try { - $SharedMailboxList = (New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenant)/Mailbox" -Tenantid $tenant -scope ExchangeOnline | Where-Object { $_.RecipientTypeDetails -EQ "SharedMailbox" -or $_.RecipientTypeDetails -eq 'SchedulingMailbox' }) | ForEach-Object { - New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/users/$($_.ObjectKey)" -type "PATCH" -body '{"accountEnabled":"false"}' -tenantid $tenant - } - Write-LogMessage -API "Standards" -tenant $tenant -message "AAD Accounts for shared mailboxes disabled." -sev Info - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable AAD accounts for shared mailboxes. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DisableTenantCreation/function.json b/Standards_DisableTenantCreation/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableTenantCreation/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableTenantCreation/run.ps1 b/Standards_DisableTenantCreation/run.ps1 deleted file mode 100644 index 39e4057fea98..000000000000 --- a/Standards_DisableTenantCreation/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -param($tenant) - -try { - $body = '{"defaultUserRolePermissions":{"allowedToCreateTenants":false}}' - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -Type patch -Body $body -ContentType "application/json") - Write-LogMessage -API "Standards" -tenant $tenant -message "Standards API: Disabled users from creating tenants." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable users from creating tenants: $($_.exception.message)" -sev "Error" -} diff --git a/Standards_DisableUserSiteCreate/function.json b/Standards_DisableUserSiteCreate/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_DisableUserSiteCreate/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableUserSiteCreate/run.ps1 b/Standards_DisableUserSiteCreate/run.ps1 deleted file mode 100644 index 3cb87b68e47d..000000000000 --- a/Standards_DisableUserSiteCreate/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -param($tenant) - -try { - $body = '{"isSiteCreationEnabled": false}' - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/sharepoint/settings" -AsApp $true -Type patch -Body $body -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled standard users from creating sites" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable standard users from creating sites: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_DisableViva/function.json b/Standards_DisableViva/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_DisableViva/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_DisableViva/run.ps1 b/Standards_DisableViva/run.ps1 deleted file mode 100644 index 89b50ec0dd62..000000000000 --- a/Standards_DisableViva/run.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -param($tenant) - -try { - $MailboxesNoArchive = (New-ExoRequest -tenantid $tenant -cmdlet "get-mailbox" -cmdparams @{ Filter = 'RecipientTypeDetails -Eq "UserMailbox"' }) | ForEach-Object { - (New-ExoRequest -tenantid $tenant -cmdlet "Set-UserBriefingConfig" -cmdparams @{ Identity = $_.UserPrincipalName; Enabled = $false }) - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Disable daily Viva reports" -sev Info - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable Viva for all users Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_EnableAppConsentRequests/function.json b/Standards_EnableAppConsentRequests/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_EnableAppConsentRequests/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_EnableAppConsentRequests/run.ps1 b/Standards_EnableAppConsentRequests/run.ps1 deleted file mode 100644 index 03d3e12bc621..000000000000 --- a/Standards_EnableAppConsentRequests/run.ps1 +++ /dev/null @@ -1,66 +0,0 @@ -param($tenant) - -try { - - $ConfigTable = Get-CippTable -tablename 'standards' - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.EnableAppConsentRequests - if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.EnableAppConsentRequests - } - - # Get current state - $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/adminConsentRequestPolicy' -tenantid $Tenant - - # Change state to enabled with default settings - $CurrentInfo.isEnabled = 'true' - $CurrentInfo.notifyReviewers = 'true' - $CurrentInfo.remindersEnabled = 'true' - $CurrentInfo.requestDurationInDays = 30 - - # Roles from standards table - $RolesToAdd = $Setting.ReviewerRoles.value - $RoleNames = $Setting.ReviewerRoles.label -join ', ' - - # Set default if no roles are selected - if (!$RolesToAdd) { - $RolesToAdd = @('62e90394-69f5-4237-9190-012177145e10') - $RoleNames = '(Default) Global Administrator' - } - - $NewReviewers = foreach ($Role in $RolesToAdd) { - @{ - query = "/beta/roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$Role'" - queryType = 'MicrosoftGraph' - queryRoot = 'null' - } - } - - # Add existing reviewers - $Reviewers = [System.Collections.Generic.List[object]]::new() - foreach ($Reviewer in $CurrentInfo.reviewers) { - $RoleFound = $false - foreach ($Role in $RolesToAdd) { - if ($Reviewer.query -match $Role -or $Reviewers.query -contains $Reviewer.query) { - $RoleFound = $true - } - } - if (!$RoleFound) { - $Reviewers.add($Reviewer) - } - } - - # Add new reviewer roles - foreach ($NewReviewer in $NewReviewers) { - $Reviewers.add($NewReviewer) - } - - # Update reviewer list - $CurrentInfo.reviewers = @($Reviewers) - $body = (ConvertTo-Json -Compress -Depth 10 -InputObject $CurrentInfo) - - New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/adminConsentRequestPolicy' -Type put -Body $body -ContentType 'application/json' - Write-LogMessage -API 'Standards' -tenant $tenant -message "Enabled App consent admin requests for the following roles: $RoleNames" -sev Info - -} catch { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable App consent admin requests. Error: $($_.exception.message)" -sev Error -} diff --git a/Standards_EnableFIDO2/function.json b/Standards_EnableFIDO2/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_EnableFIDO2/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_EnableFIDO2/run.ps1 b/Standards_EnableFIDO2/run.ps1 deleted file mode 100644 index 5618871add43..000000000000 --- a/Standards_EnableFIDO2/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -param($tenant) - -try { - $body = '{"@odata.type":"#microsoft.graph.fido2AuthenticationMethodConfiguration","id":"Fido2","includeTargets":[{"id":"all_users","isRegistrationRequired":false,"targetType":"group","displayName":"All users"}],"excludeTargets":[],"isAttestationEnforced":true,"isSelfServiceRegistrationAllowed":true,"keyRestrictions":{"aaGuids":[],"enforcementType":"block","isEnforced":false},"state":"enabled"}' - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationmethodspolicy/authenticationMethodConfigurations/Fido2" -Type patch -Body $body -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled FIDO2 Support" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable FIDO2 Support: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_EnableOnlineArchiving/function.json b/Standards_EnableOnlineArchiving/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_EnableOnlineArchiving/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_EnableOnlineArchiving/run.ps1 b/Standards_EnableOnlineArchiving/run.ps1 deleted file mode 100644 index b8634b7ca07f..000000000000 --- a/Standards_EnableOnlineArchiving/run.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -param($tenant) - -try { - $MailboxesNoArchive = (New-ExoRequest -tenantid $tenant -cmdlet "get-mailbox" -cmdparams @{ Filter = 'ArchiveGuid -Eq "00000000-0000-0000-0000-000000000000" -AND RecipientTypeDetails -Eq "UserMailbox"' }) | ForEach-Object { - (New-ExoRequest -tenantid $tenant -cmdlet "enable-Mailbox" -cmdparams @{ Identity = $_.UserPrincipalName; Archive = $true }) - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled Online Archiving for all accounts" -sev Info - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to Enable Online Archiving for all accounts Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_ExConnector/function.json b/Standards_ExConnector/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_ExConnector/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_ExConnector/run.ps1 b/Standards_ExConnector/run.ps1 deleted file mode 100644 index 9250918a0279..000000000000 --- a/Standards_ExConnector/run.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.ExConnector -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.ExConnector -} -$APINAME = "Standards" -foreach ($Template in $Setting.TemplateList) { - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'ExConnectorTemplate' and RowKey eq '$($Template.value)'" - $connectorType = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).direction - $RequestParams = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet "Get-$($ConnectorType)connector" | Where-Object -Property Identity -EQ $RequestParams.name - if ($Existing) { - $RequestParams | Add-Member -NotePropertyValue $Existing.Identity -NotePropertyName Identity -Force - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "Set-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true - Write-LogMessage -API $APINAME -tenant $Tenant -message "Updated transport rule for $($Tenant)" -sev info - } - else { - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true - Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($Tenant)" -sev info - } - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to create or update Exchange Connector Rule: $($_.exception.message)" -sev "Error" - } - -} - diff --git a/Standards_ExcludedfileExt/function.json b/Standards_ExcludedfileExt/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_ExcludedfileExt/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_ExcludedfileExt/run.ps1 b/Standards_ExcludedfileExt/run.ps1 deleted file mode 100644 index e8620848f04d..000000000000 --- a/Standards_ExcludedfileExt/run.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -param($tenant) -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.ExcludedfileExt -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.ExcludedfileExt -} - -try { - $Exts = $Setting.ext -split ',' - $body = ConvertTo-Json -InputObject @{ excludedFileExtensionsForSyncApp = @($Exts) } - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/sharepoint/settings" -AsApp $true -Type patch -Body $body -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Added $($Setting.ext) to excluded synced files" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to add $($Setting.ext) to excluded synced files: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_GetQueue/function.json b/Standards_GetQueue/function.json deleted file mode 100644 index b31f1ad21352..000000000000 --- a/Standards_GetQueue/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "name", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_GetQueue/run.ps1 b/Standards_GetQueue/run.ps1 deleted file mode 100644 index 24a4f64dc523..000000000000 --- a/Standards_GetQueue/run.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -param($name) - -Write-Host 'QUEUEQUE' -$Table = Get-CippTable -tablename 'standards' -$SkipList = Get-Tenants -SkipList -$Tenants = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - -$object = foreach ($Tenant in $Tenants) { - $Tenant.standards.psobject.properties.name | ForEach-Object { - $Standard = $_ - Write-Host "Standard is $Standard" - if ($Tenant.Tenant -ne 'AllTenants' -and $SkipList.defaultDomainName -notcontains $Tenant.Tenant) { - Write-Host 'Not all tenants. Single object' - if ($Standard -ne "OverrideAllTenants") { - [pscustomobject]@{ - Tenant = $tenant.Tenant - Standard = $Standard - } - } - } - elseif ($Tenant.Tenant -eq 'AllTenants') { - Get-Tenants | ForEach-Object { - $TenantForStandard = $_ - $TenantStandard = $Tenants | Where-Object { $_.Tenant -eq $TenantForStandard.defaultDomainName } - Write-Host "Working on all Tenants. Current Tenant is $($Tenant.defaultDomainName) and standard is $Standard" - if ($TenantStandard.standards.OverrideAllTenants -ne $true) { - [pscustomobject]@{ - Tenant = $_.defaultDomainName - Standard = $Standard - } - } - } - } - } -} - -$object \ No newline at end of file diff --git a/Standards_GroupTemplate/function.json b/Standards_GroupTemplate/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_GroupTemplate/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_GroupTemplate/run.ps1 b/Standards_GroupTemplate/run.ps1 deleted file mode 100644 index 4034f513e5ac..000000000000 --- a/Standards_GroupTemplate/run.ps1 +++ /dev/null @@ -1,61 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.GroupTemplate -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.GroupTemplate -} - - - -foreach ($Template in $Setting.TemplateList) { - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$($Template.value)'" - $groupobj = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($tenant)" } - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/groups" -tenantid $tenant | Where-Object -Property displayName -EQ $groupobj.displayname - if (!$CheckExististing) { - if ($groupobj.groupType -in "Generic", "azurerole", "dynamic") { - - $BodyToship = [pscustomobject] @{ - "displayName" = $groupobj.Displayname - "description" = $groupobj.Description - "mailNickname" = $groupobj.username - mailEnabled = [bool]$false - securityEnabled = [bool]$true - isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ "AzureRole") - - } - if ($groupobj.membershipRules) { - $BodyToship | Add-Member -NotePropertyName "membershipRule" -NotePropertyValue ($groupobj.membershipRules) - $BodyToship | Add-Member -NotePropertyName "groupTypes" -NotePropertyValue @("DynamicMembership") - $BodyToship | Add-Member -NotePropertyName "membershipRuleProcessingState" -NotePropertyValue "On" - } - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups" -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose - } - else { - $Params = @{ - Name = $groupobj.Displayname - Alias = $groupobj.username - Description = $groupobj.Description - PrimarySmtpAddress = $email - Type = $groupobj.groupType - RequireSenderAuthenticationEnabled = [bool]!$groupobj.AllowExternal - } - $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet "New-DistributionGroup" -cmdParams $params - } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API "Standards" -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) " -Sev "Info" - - } - else { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API "Standards" -tenant $tenant -message "Group exists $($groupobj.displayname). Did not create" -Sev "Info" - - } - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to create group: $($_.exception.message)" -sev "Error" - } -} - - diff --git a/Standards_IntuneTemplate/function.json b/Standards_IntuneTemplate/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_IntuneTemplate/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_IntuneTemplate/run.ps1 b/Standards_IntuneTemplate/run.ps1 deleted file mode 100644 index d33febabede5..000000000000 --- a/Standards_IntuneTemplate/run.ps1 +++ /dev/null @@ -1,88 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.IntuneTemplate -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.IntuneTemplate -} - -$APINAME = "Standards" -foreach ($Template in $Setting.TemplateList) { - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'IntuneTemplate'" - $Request = @{body = $null } - $Request.body = (Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object -Property RowKey -Like "$($template.value)*").JSON | ConvertFrom-Json - $displayname = $request.body.Displayname - $description = $request.body.Description - $AssignTo = if ($request.body.Assignto -ne "on") { $request.body.Assignto } - $RawJSON = $Request.body.RawJSON - - switch ($Request.body.Type) { - "Admin" { - $TemplateTypeURL = "groupPolicyConfigurations" - $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($displayname -in $CheckExististing.displayName) { - $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname - $ExistingData = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/definitionValues" -tenantid $tenant - $DeleteJson = $RawJSON | ConvertFrom-Json -Depth 10 - $DeleteJson.deletedIds = @($ExistingData.id) - $DeleteJson.added = @() - $DeleteJson = ConvertTo-Json -Depth 10 -InputObject $DeleteJson - $DeleteRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $DeleteJson - $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($Displayname) to template defaults" -Sev "info" - - } - else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $CreateBody - $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname) to template defaults" -Sev "info" - - } - } - "Device" { - $TemplateTypeURL = "deviceConfigurations" - $PolicyName = ($RawJSON | ConvertFrom-Json).displayName - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($PolicyName -in $CheckExististing.displayName) { - $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName - $PatchRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($PolicyName) to template defaults" -Sev "info" - - } - else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev "info" - - } - } - "Catalog" { - $TemplateTypeURL = "configurationPolicies" - $PolicyName = ($RawJSON | ConvertFrom-Json).Name - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($PolicyName -in $CheckExististing.name) { - $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName - $PUTRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON - - } - else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev "info" - - } - } - - } - if ($AssignTo) { - $AssignBody = if ($AssignTo -ne "AllDevicesAndUsers") { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $AssignTo" -Sev "Info" - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Successfully added Intune Template policy for $($Tenant)" -sev "Info" - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to create or update Intune Template: $($_.exception.message)" -sev "Error" - } -} diff --git a/Standards_LegacyMFA/function.json b/Standards_LegacyMFA/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_LegacyMFA/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_LegacyMFA/run.ps1 b/Standards_LegacyMFA/run.ps1 deleted file mode 100644 index c0bdd2f8501c..000000000000 --- a/Standards_LegacyMFA/run.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -param($tenant) - -try { - $AADGraphtoken = (Get-GraphToken -scope 'https://graph.windows.net/.default') - $tenantid = (Get-Tenants | Where-Object -Property defaultDomainName -EQ $Tenant).customerId - $TrackingGuid = (New-Guid).GUID - $LogonPost = @" -http://provisioning.microsoftonline.com/IProvisioningWebService/MsolConnecturn:uuid:$TrackingGuidhttp://www.w3.org/2005/08/addressing/anonymous$($AADGraphtoken['Authorization'])50afce61-c917-435b-8c6d-60aa5a8b8aa71.2.183.57Version47$($TrackingGuid)https://provisioningapi.microsoftonline.com/provisioningwebservice.svcVersion4 -"@ - $DataBlob = (Invoke-RestMethod -Method POST -Uri 'https://provisioningapi.microsoftonline.com/provisioningwebservice.svc' -ContentType 'application/soap+xml; charset=utf-8' -Body $LogonPost).envelope.header.BecContext.DataBlob.'#text' - $Users = Get-CIPPMSolUsers -tenant $tenant | Where-Object { ($_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state -eq $null -and $_.UserPrincipalName -notlike 'Sync_*') } - foreach ($user in $users) { - Write-Host $user.UserPrincipalName - $MSOLXML = @" -http://provisioning.microsoftonline.com/IProvisioningWebService/SetUserurn:uuid:$TrackingGuidhttp://www.w3.org/2005/08/addressing/anonymous$($AADGraphtoken['Authorization'])$($DataBlob)9450afce61-c917-435b-8c6d-60aa5a8b8aa71.2.183.57Version47$TrackingGuidhttps://provisioningapi.microsoftonline.com/provisioningwebservice.svcVersion16$($tenantid)$($User.ObjectID)*0001-01-01T00:00:00Enabled -"@ - $SetMFA = (Invoke-RestMethod -Uri 'https://provisioningapi.microsoftonline.com/provisioningwebservice.svc' -Method post -Body $MSOLXML -ContentType 'application/soap+xml; charset=utf-8') - } - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled per user MFA.' -sev Info - -} -catch { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable (legacy) per user MFA: $($_.exception.message)" -sev "Error" -} \ No newline at end of file diff --git a/Standards_LegacyMFACleanup/function.json b/Standards_LegacyMFACleanup/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_LegacyMFACleanup/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_LegacyMFACleanup/run.ps1 b/Standards_LegacyMFACleanup/run.ps1 deleted file mode 100644 index ba87338262d1..000000000000 --- a/Standards_LegacyMFACleanup/run.ps1 +++ /dev/null @@ -1,63 +0,0 @@ -param($tenant) - -try { - $AADGraphtoken = (Get-GraphToken -scope 'https://graph.windows.net/.default') - $tenantid = (Get-Tenants | Where-Object -Property defaultDomainName -EQ $tenant).customerId - - try { - $SecureDefaultsState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -tenantid $tenant) - $SecDefaults = $SecureDefaultsState.IsEnabled - Write-LogMessage -API 'Standards' -tenant $tenant -message "Security default state: $SecDefaults" -sev Debug - } - catch { - $SecDefaults = $false - } - - if ($SecDefaults -eq $false) { - try { - $AllUsersCAPolicy = (New-GraphGetRequest -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies?`$filter=(grantControls/builtInControls/any(b:b eq 'mfa') or grantControls/customAuthenticationFactors/any(c:c eq 'RequireDuoMfa')) and state eq 'enabled' and conditions/users/includeUsers/any(u:u eq 'All')&`$count=true" -ComplexFilter -tenantid $tenant).displayName - Write-LogMessage -API 'Standards' -tenant $tenant -message "All users CA policy: $AllUsersCAPolicy" -sev Debug - - if ($AllUsersCAPolicy) { - $AADPremiumUsers = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/?`$select=id,userPrincipalName&`$filter=assignedPlans/any(c:c/service eq 'AADPremiumService' and c/capabilityStatus eq 'Enabled')&`$count=true" -tenantid $tenant -ComplexFilter).userPrincipalName - Write-LogMessage -API 'Standards' -tenant $tenant -message "AAD Premium Users: $($AADPremiumUsers -join ', ')" -sev Debug - } - } - catch { - $AllUsersCAPolicy = $false - } - } - - if ($SecDefaults -or $AllUsersCAPolicy) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Tenant meets requirements for Legacy MFA cleanup' -sev Info - $TrackingGuid = (New-Guid).GUID - $LogonPost = @" -http://provisioning.microsoftonline.com/IProvisioningWebService/MsolConnecturn:uuid:$TrackingGuidhttp://www.w3.org/2005/08/addressing/anonymous$($AADGraphtoken['Authorization'])50afce61-c917-435b-8c6d-60aa5a8b8aa71.2.183.57Version47$($TrackingGuid)https://provisioningapi.microsoftonline.com/provisioningwebservice.svcVersion4 -"@ - $DataBlob = (Invoke-RestMethod -Method POST -Uri 'https://provisioningapi.microsoftonline.com/provisioningwebservice.svc' -ContentType 'application/soap+xml; charset=utf-8' -Body $LogonPost).envelope.header.BecContext.DataBlob.'#text' - $Users = Get-CIPPMSolUsers -tenant $tenant | Where-Object { $_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.State -eq 'Enabled' -or $_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.State -EQ 'Enforced' } - if (($Users | Measure-Object | Select-Object -ExpandProperty Count) -gt 0) { - foreach ($user in $users) { - if ($AllUsersCAPolicy -and $AADPremiumUsers -notcontains $user.UserPrincipalName) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Skipping user $($user.UserPrincipalName) does not have AAD Premium" -sev Debug - continue - } - Write-LogMessage -API 'Standards' -tenant $tenant -message "Disabling legacy MFA for $($user.UserPrincipalName)" -sev Info - $MSOLXML = @" -http://provisioning.microsoftonline.com/IProvisioningWebService/SetUserurn:uuid:$TrackingGuidhttp://www.w3.org/2005/08/addressing/anonymous$($AADGraphtoken['Authorization'])$($DataBlob)9450afce61-c917-435b-8c6d-60aa5a8b8aa71.2.183.57Version47$TrackingGuidhttps://provisioningapi.microsoftonline.com/provisioningwebservice.svcVersion16$($tenantid)$($User.ObjectID) -"@ - $SetMFA = (Invoke-RestMethod -Uri 'https://provisioningapi.microsoftonline.com/provisioningwebservice.svc' -Method post -Body $MSOLXML -ContentType 'application/soap+xml; charset=utf-8') - } - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Legacy MFA cleanup complete.' -sev Info - } - else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'No Legacy MFA to cleanup.' -sev Info - } - } - else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Unable to clean up per user MFA, tenant does not have Security Defaults or an all users CA policy requiring MFA' -sev Error - } -} -catch { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to clean up (legacy) per user MFA: $($_.exception.message)" -sev "Error" -} \ No newline at end of file diff --git a/Standards_MailContacts/function.json b/Standards_MailContacts/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_MailContacts/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_MailContacts/run.ps1 b/Standards_MailContacts/run.ps1 deleted file mode 100644 index 83cbd4bea699..000000000000 --- a/Standards_MailContacts/run.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -param($tenant) -$ConfigTable = Get-CippTable -tablename 'standards' -$Contacts = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.MailContacts -if (!$Contacts) { - $Contacts = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.MailContacts -} - -try { - $TenantID = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/organization" -tenantid $tenant) - $Body = [pscustomobject]@{} - switch ($Contacts) { - { $Contacts.marketingcontact.mail } { $body | Add-Member -NotePropertyName marketingNotificationEmails -NotePropertyValue @($Contacts.marketingcontact.mail) } - { $Contacts.SecurityContact.Mail } { $body | Add-Member -NotePropertyName securityComplianceNotificationMails -NotePropertyValue @($Contacts.SecurityContact.Mail) } - { $Contacts.TechContact.Mail } { $body | Add-Member -NotePropertyName technicalNotificationMails -NotePropertyValue @($Contacts.TechContact.Mail) } - { $Contacts.GeneralContact.Mail } { $body | Add-Member -NotePropertyName privacyProfile -NotePropertyValue @{contactEmail = $Contacts.GeneralContact.Mail } } - } - Write-Host (ConvertTo-Json -InputObject $body) - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/organization/$($TenantID.id)" -Type patch -Body (ConvertTo-Json -InputObject $body) -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Contact email's set." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set contact emails: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_ModernAuth/function.json b/Standards_ModernAuth/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_ModernAuth/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_ModernAuth/run.ps1 b/Standards_ModernAuth/run.ps1 deleted file mode 100644 index 396045f532bc..000000000000 --- a/Standards_ModernAuth/run.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -param($tenant) - -Write-LogMessage -API "Standards" -tenant $tenant -message "Modern Authentication is enabled by default. This standard is no longer required." -sev Info diff --git a/Standards_NudgeMFA/function.json b/Standards_NudgeMFA/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_NudgeMFA/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_NudgeMFA/run.ps1 b/Standards_NudgeMFA/run.ps1 deleted file mode 100644 index 0ec7b80ef78d..000000000000 --- a/Standards_NudgeMFA/run.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.NudgeMFA -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.NudgeMFA -} -Write-Output $setting -$status = if ($Setting.enable -and $Setting.disable) { - Write-LogMessage -API "Standards" -tenant $tenant -message "You cannot both enable and disable the Nudge MFA setting" -sev Error - Exit -} -elseif ($setting.enable) { "enabled" } else { "disabled" } -Write-Output $status -try { - $Body = (New-GraphGetRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy") - $body.registrationEnforcement.authenticationMethodsRegistrationCampaign.state = $status - $body = ConvertTo-Json -Depth 10 -InputObject ($body | Select-Object registrationEnforcement) - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy" -Type patch -Body $body -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Authenticator App Nudge/Registration campaign $status." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to $status Authenticator App Nudge/Registration campaign: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_OauthConsent/function.json b/Standards_OauthConsent/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_OauthConsent/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_OauthConsent/run.ps1 b/Standards_OauthConsent/run.ps1 deleted file mode 100644 index 03479b028411..000000000000 --- a/Standards_OauthConsent/run.ps1 +++ /dev/null @@ -1,36 +0,0 @@ -param($tenant) -$ConfigTable = Get-CippTable -tablename 'standards' -$AllowedAppIdsForTenant = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).Standards.OauthConsent.AllowedApps -split ',' -if (!$AllowedAppIdsForTenant) { - $AllowedAppIdsForTenant = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).Standards.OauthConsent.AllowedApps -split ',' -} -try { - $State = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -tenantid $tenant) - if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @("ManagePermissionGrantsForSelf.cipp-1sent-policy")) { - Write-Host "Going to set" - - $Existing = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/policies/permissionGrantPolicies/" -tenantid $tenant) | Where-Object -Property id -EQ "cipp-consent-policy" - if (!$Existing) { - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/permissionGrantPolicies" -Type POST -Body '{ "id":"cipp-consent-policy", "displayName":"Application Consent Policy", "description":"This policy controls the current application consent policies."}' -ContentType "application/json" - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/permissionGrantPolicies/cipp-consent-policy/includes" -Type POST -Body '{"permissionClassification":"all","permissionType":"delegated","clientApplicationIds":["d414ee2d-73e5-4e5b-bb16-03ef55fea597"]}' -ContentType "application/json" - } - try { - foreach ($AllowedApp in $AllowedAppIdsForTenant) { - Write-Host "$AllowedApp" - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/permissionGrantPolicies/cipp-consent-policy/includes" -Type POST -Body ('{"permissionType": "delegated","clientApplicationIds": ["' + $AllowedApp + '"]}') -ContentType "application/json" - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/permissionGrantPolicies/cipp-consent-policy/includes" -Type POST -Body ('{ "permissionType": "Application", "clientApplicationIds": ["' + $AllowedApp + '"] }') -ContentType "application/json" - } - } - catch { - "Could not add exclusions, probably already exist: $($_)" - } - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["managePermissionGrantsForSelf.cipp-consent-policy"]}' -ContentType "application/json" - } - if ($AllowedAppIdsForTenant) { - } - - Write-LogMessage -API "Standards" -tenant $tenant -message "Application Consent Mode has been enabled." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to apply Application Consent Mode Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_OauthConsentLowSec/function.json b/Standards_OauthConsentLowSec/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_OauthConsentLowSec/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_OauthConsentLowSec/run.ps1 b/Standards_OauthConsentLowSec/run.ps1 deleted file mode 100644 index 9e4278f153fd..000000000000 --- a/Standards_OauthConsentLowSec/run.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -param($tenant) - -try { - $State = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -tenantid $tenant) - if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @("managePermissionGrantsForSelf.microsoft-user-default-low")) { - Write-Host "Going to set" - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["managePermissionGrantsForSelf.microsoft-user-default-low"]}' -ContentType "application/json" - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Application Consent Mode(microsoft-user-default-low) has been enabled." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to apply Application Consent Mode (microsoft-user-default-low) Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_Orchestration/function.json b/Standards_Orchestration/function.json deleted file mode 100644 index 7326b39c184d..000000000000 --- a/Standards_Orchestration/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "Context", - "type": "orchestrationTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_Orchestration/run.ps1 b/Standards_Orchestration/run.ps1 deleted file mode 100644 index 5e20d3ed21d4..000000000000 --- a/Standards_Orchestration/run.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -param($Context) - -$DurableRetryOptions = @{ - FirstRetryInterval = (New-TimeSpan -Seconds 5) - MaxNumberOfAttempts = 3 - BackoffCoefficient = 2 -} -$RetryOptions = New-DurableRetryOptions @DurableRetryOptions - -$Batch = Invoke-ActivityFunction -FunctionName 'Standards_GetQueue' -Input 'LetsGo' -ErrorAction Stop -if ($null -ne $Batch -and ($Batch | Measure-Object).Count -gt 0) { - $ParallelTasks = foreach ($Item in $Batch) { - if ($item['Standard']) { - try { - Invoke-DurableActivity -FunctionName "Standards_$($item['Standard'])" -Input "$($item['Tenant'])" -NoWait -RetryOptions $RetryOptions -ErrorAction Stop - } catch { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Task error: $($_.Exception.Message)" -sev Error - } - } - } - - if (($ParallelTasks | Measure-Object).Count -gt 0) { - try { - $Outputs = Wait-ActivityFunction -Task $ParallelTasks -ErrorAction Stop - } catch { - Write-Information "Standards Wait-ActivityFunction error: $($_.Exception.Message)" - } - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Deployment finished.' -sev Info - } -} else { - Write-Information 'No Standards to process' -} diff --git a/Standards_OrchestrationStarter/function.json b/Standards_OrchestrationStarter/function.json deleted file mode 100644 index 14c44f4f0217..000000000000 --- a/Standards_OrchestrationStarter/function.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "bindings": [ - { - "authLevel": "anonymous", - "name": "Request", - "type": "httpTrigger", - "direction": "in", - "methods": [ - "post", - "get" - ] - }, - { - "type": "http", - "direction": "out", - "name": "Response" - }, - { - "name": "starter", - "type": "durableClient", - "direction": "in" - } - ] -} diff --git a/Standards_OrchestrationStarter/run.ps1 b/Standards_OrchestrationStarter/run.ps1 deleted file mode 100644 index 514c3edf0980..000000000000 --- a/Standards_OrchestrationStarter/run.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -using namespace System.Net - -param($Request, $TriggerMetadata) -if ($CurrentlyRunning) { - $Results = [pscustomobject]@{"Results" = "Already running. Please wait for the current instance to finish" } - Write-LogMessage -API "StandardsApply" -message "Attempted to Standards but an instance was already running." -sev Info -} -else { - $InstanceId = Start-NewOrchestration -FunctionName 'Standards_Orchestration' - Write-Host "Started orchestration with ID = '$InstanceId'" - $Response = New-OrchestrationCheckStatusResponse -Request $Request -InstanceId $InstanceId - Write-Host ($Response | ConvertTo-Json) - Write-LogMessage -API "Standards" -tenant $tenant -message "Started applying the standard templates to tenants." -sev Info - $Results = [pscustomobject]@{"Results" = "Started Applying Standards" } -} -Write-Host ($Orchestrator | ConvertTo-Json) - - -Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $results - }) \ No newline at end of file diff --git a/Standards_OrchestrationStarterTimer/run.ps1 b/Standards_OrchestrationStarterTimer/run.ps1 deleted file mode 100644 index 4fa90a9e8720..000000000000 --- a/Standards_OrchestrationStarterTimer/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -using namespace System.Net - -param($Timer) - -$InstanceId = Start-NewOrchestration -FunctionName 'Standards_Orchestration' -Write-Host "Started orchestration with ID = '$InstanceId'" - -$Response = New-OrchestrationCheckStatusResponse -Request $timer -InstanceId $InstanceId -Write-Host ($Response | ConvertTo-Json) -Write-LogMessage -API "Standards" -tenant $tenant -message "Started applying the standard templates to tenants." -sev Info diff --git a/Standards_OutBoundSpamAlert/function.json b/Standards_OutBoundSpamAlert/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_OutBoundSpamAlert/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_OutBoundSpamAlert/run.ps1 b/Standards_OutBoundSpamAlert/run.ps1 deleted file mode 100644 index 68b3b1952e60..000000000000 --- a/Standards_OutBoundSpamAlert/run.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -param($tenant) -$ConfigTable = Get-CippTable -tablename 'standards' -$Contacts = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.OutBoundSpamAlert -if (!$Contacts) { - $Contacts = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.OutBoundSpamAlert -} - -try { - New-ExoRequest -tenantid $tenant -cmdlet "Set-HostedOutboundSpamFilterPolicy" -cmdparams @{ Identity = "Default"; NotifyOutboundSpam = $true; NotifyOutboundSpamRecipients = $Contacts.OutboundSpamContact } -useSystemMailbox $true - Write-LogMessage -API "Standards" -tenant $tenant -message "Set outbound spam filter alert to $($Contacts.OutboundSpamContact)" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set outbound spam contact to $($Contacts.OutboundSpamContact). $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_PWcompanionAppAllowedState/function.json b/Standards_PWcompanionAppAllowedState/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_PWcompanionAppAllowedState/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_PWcompanionAppAllowedState/run.ps1 b/Standards_PWcompanionAppAllowedState/run.ps1 deleted file mode 100644 index ef0dbd2b255f..000000000000 --- a/Standards_PWcompanionAppAllowedState/run.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.PWcompanionAppAllowedState -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.PWcompanionAppAllowedState -} - -try { - - # Get current state of microsoftAuthenticator policy - $authenticatorFeaturesState = (New-GraphGetRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type GET) - - # Remove number matching from featureSettings because this is now Microsoft enforced and shipping it returns an error - $authenticatorFeaturesState.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') - - # Define feature body - $featureBody = @{ - state = $Setting.state - includeTarget = [PSCustomObject]@{ - targetType = 'group' - id = 'all_users' - } - excludeTarget = [PSCustomObject]@{ - targetType = 'group' - id = '00000000-0000-0000-0000-000000000000' - } - } - - # Set body for companionAppAllowedState - $authenticatorFeaturesState.featureSettings.companionAppAllowedState = $featureBody - - $body = $authenticatorFeaturesState | ConvertTo-Json -Depth 3 - - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") - - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled companionAppAllowedState." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable companionAppAllowedState. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_PWdisplayAppInformationRequiredState/function.json b/Standards_PWdisplayAppInformationRequiredState/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_PWdisplayAppInformationRequiredState/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_PWdisplayAppInformationRequiredState/run.ps1 b/Standards_PWdisplayAppInformationRequiredState/run.ps1 deleted file mode 100644 index 3f59c422019e..000000000000 --- a/Standards_PWdisplayAppInformationRequiredState/run.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -param($tenant) - -try { - - $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -tenantid $Tenant - $CurrentInfo.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') - $CurrentInfo.featureSettings.displayAppInformationRequiredState.state = "enabled" - $CurrentInfo.featureSettings.displayLocationInformationRequiredState.state = "enabled" - $body = ($CurrentInfo | ConvertTo-Json -depth 10) - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") - - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled passwordless with Information and Number Matching." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable passwordless with Information and Number Matching. Error: $($_.exception.message)" -sev "Error" -} \ No newline at end of file diff --git a/Standards_PWnumberMatchingRequiredState/function.json b/Standards_PWnumberMatchingRequiredState/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_PWnumberMatchingRequiredState/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_PWnumberMatchingRequiredState/run.ps1 b/Standards_PWnumberMatchingRequiredState/run.ps1 deleted file mode 100644 index 65f5c3383852..000000000000 --- a/Standards_PWnumberMatchingRequiredState/run.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -param($tenant) - -try { - Write-LogMessage -API "Standards" -tenant $tenant -message "Passwordless with number matching is now enabled by default." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable passwordless with Number Matching. Error: $($_.exception.message)" -sev "Error" -} \ No newline at end of file diff --git a/Standards_PasswordExpireDisabled/function.json b/Standards_PasswordExpireDisabled/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_PasswordExpireDisabled/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_PasswordExpireDisabled/run.ps1 b/Standards_PasswordExpireDisabled/run.ps1 deleted file mode 100644 index 58f5cdb972b7..000000000000 --- a/Standards_PasswordExpireDisabled/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -param($tenant) -try { - $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/domains" -tenantid $Tenant | Where-Object -Property passwordValidityPeriodInDays -NE '2147483647' | ForEach-Object { - New-GraphPostRequest -type Patch -tenantid $Tenant -uri "https://graph.microsoft.com/beta/domains/$($_.id)" -body '{"passwordValidityPeriodInDays": 2147483647 }' - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled Password Expiration" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable Password Expiration. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_RotateDKIM/function.json b/Standards_RotateDKIM/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_RotateDKIM/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_RotateDKIM/run.ps1 b/Standards_RotateDKIM/run.ps1 deleted file mode 100644 index 6472d8d055c6..000000000000 --- a/Standards_RotateDKIM/run.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -param($tenant) - -try { - $DKIM = (New-ExoRequest -tenantid $tenant -cmdlet "Get-DkimSigningConfig") | Where-Object { $_.Selector1KeySize -EQ 1024 -and $_.Enabled -eq $true } | ForEach-Object { - (New-ExoRequest -tenantid $tenant -cmdlet "Rotate-DkimSigningConfig" -cmdparams @{ KeySize = 2048; Identity = $_.Identity } -useSystemMailbox $true) - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Rotated DKIM" -sev Info - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to rotate DKIM Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_SSPR/function.json b/Standards_SSPR/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_SSPR/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_SSPR/run.ps1 b/Standards_SSPR/run.ps1 deleted file mode 100644 index 3b0bbb7da943..000000000000 --- a/Standards_SSPR/run.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -param($tenant) -try { - Write-LogMessage -API "Standards" -tenant $tenant -message "SSPR standard is no longer available" -sev Error -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable SSPR $($_.exception.message)" -sev "Error" -} \ No newline at end of file diff --git a/Standards_SafeSendersDisable/function.json b/Standards_SafeSendersDisable/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_SafeSendersDisable/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_SafeSendersDisable/run.ps1 b/Standards_SafeSendersDisable/run.ps1 deleted file mode 100644 index 1c5cb1d0feb1..000000000000 --- a/Standards_SafeSendersDisable/run.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -param($tenant) - -try { - $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet "Get-Mailbox" | ForEach-Object { - try { - $username = $_.UserPrincipalName - New-ExoRequest -tenantid $Tenant -cmdlet "Set-MailboxJunkEmailConfiguration" -cmdParams @{Identity = $_.GUID ; TrustedRecipientsAndDomains = $null } -anchor $username - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not disbale SafeSenders list for $($username): $($_.Exception.message)" -sev Warn - } - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Safe Senders disabled" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable SafeSenders. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_SecurityDefaults/function.json b/Standards_SecurityDefaults/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_SecurityDefaults/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_SecurityDefaults/run.ps1 b/Standards_SecurityDefaults/run.ps1 deleted file mode 100644 index 09bb20f772e7..000000000000 --- a/Standards_SecurityDefaults/run.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -param($tenant) - -try { - $SecureDefaultsState = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy" -tenantid $tenant) - - if ($SecureDefaultsState.IsEnabled -ne $true) { - Write-Host "Secure Defaults is disabled. Enabling for $tenant" -ForegroundColor Yellow - $body = '{ "isEnabled": true }' - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy" -Type patch -Body $body -ContentType "application/json") - } - Write-LogMessage -API "Standards" -tenant $tenant -message "Standards API: Security Defaults Enabled." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable Security Defaults Error: $($_.exception.message)" -sev "Error" -} \ No newline at end of file diff --git a/Standards_SendFromAlias/function.json b/Standards_SendFromAlias/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_SendFromAlias/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_SendFromAlias/run.ps1 b/Standards_SendFromAlias/run.ps1 deleted file mode 100644 index 1a6e45c06278..000000000000 --- a/Standards_SendFromAlias/run.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -param($tenant) - -try { - $AdminAuditLogParams = @{ - SendFromAliasEnabled = $true - } - New-ExoRequest -tenantid $Tenant -cmdlet "Set-OrganizationConfig" -cmdParams $AdminAuditLogParams - Write-LogMessage -API "Standards" -tenant $tenant -message "Send from alias Enabled." -sev Info - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to apply Send from Alias Standard. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_SendReceiveLimitTenant/function.json b/Standards_SendReceiveLimitTenant/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_SendReceiveLimitTenant/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_SendReceiveLimitTenant/run.ps1 b/Standards_SendReceiveLimitTenant/run.ps1 deleted file mode 100644 index 1b86b0756ddc..000000000000 --- a/Standards_SendReceiveLimitTenant/run.ps1 +++ /dev/null @@ -1,54 +0,0 @@ -param($tenant) -# Get the tenant standards settings -$ConfigTable = Get-CippTable -tablename 'standards' -$Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.SendReceiveLimitTenant.SendReceiveLimit -split ',' -if (!$Limits) { - $Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.SendReceiveLimitTenant.SendReceiveLimit -split ',' -} - -# Parse the send limits and convert to bytes -if ($Limits[0] -like "*MB*") { - $MaxSendSize = [int]($Limits[0] -Replace "[a-zA-Z]", "") * 1MB -} -elseif ($Limits[0] -like "*KB*") { - $MaxSendSize = [int]($Limits[0] -Replace "[a-zA-Z]", "") * 1KB -} # Default to 35MB if invalid input -else { - $MaxSendSize = 35MB -} -# Test if the send limit is larger allowed and correct if needed -if ($MaxSendSize -gt 150MB) { - $MaxSendSize = 150MB -} - -# Parse the receive limits and convert to bytes -if ($Limits[1] -like "*MB*") { - $MaxReceiveSize = [int]($Limits[1] -Replace "[a-zA-Z]", "") * 1MB -} -elseif ($Limits[1] -like "*KB*") { - $MaxReceiveSize = [int]($Limits[1] -Replace "[a-zA-Z]", "") * 1KB -} # Default to 36MB if invalid input -else { - $MaxReceiveSize = 36MB -} -# Test if the receive limit is larger allowed and correct if needed -if ($MaxReceiveSize -gt 150MB) { - $MaxReceiveSize = 150MB -} - -try { - # Get all mailbox plans - $AllMailBoxPlans = New-ExoRequest -tenantid $Tenant -cmdlet "Get-MailboxPlan" | Select-Object DisplayName, MaxSendSize, MaxReceiveSize, GUID - - # Loop through all mailbox plans and set the send and receive limits for each if needed - foreach ($MailboxPlan in $AllMailBoxPlans) { - if ($MailboxPlan.MaxSendSize -ne $MaxSendSize -and $MailboxPlan.MaxReceiveSize -ne $MaxReceiveSize) { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-MailboxPlan" -cmdParams @{Identity = $MailboxPlan.GUID; MaxSendSize = $MaxSendSize; MaxReceiveSize = $MaxReceiveSize } -useSystemMailbox $true - } - } - # Write to log on success - Write-LogMessage -API "Standards" -tenant $tenant -message "Successfully set the tenant send and receive limits " -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set the tenant send and receive limits. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_SpoofWarn/function.json b/Standards_SpoofWarn/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_SpoofWarn/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_SpoofWarn/run.ps1 b/Standards_SpoofWarn/run.ps1 deleted file mode 100644 index 1fc970fbe231..000000000000 --- a/Standards_SpoofWarn/run.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.spoofwarn -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.spoofwarn -} -$status = if ($Setting.enable -and $Setting.disable) { - Write-LogMessage -API "Standards" -tenant $tenant -message "You cannot both enable and disable the Spoof Warnings setting" -sev Error - Exit -} -elseif ($setting.enable) { $true } else { $false } -try { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-ExternalInOutlook" -cmdParams @{ Enabled = $status; } - Write-LogMessage -API "Standards" -tenant $tenant -message "Spoofing warnings set to $status." -sev Info - -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set spoofing warnings to $status. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_TAP/function.json b/Standards_TAP/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_TAP/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_TAP/run.ps1 b/Standards_TAP/run.ps1 deleted file mode 100644 index b7ca0a778c6e..000000000000 --- a/Standards_TAP/run.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -param($tenant) -$ConfigTable = Get-CippTable -tablename 'standards' -$TAPConfig = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).Standards.TAP.config -if (!$TAPConfig) { - $TAPConfig = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).Standards.TAP.config -} -if (!$TAPConfig) { $TAPConfig = 'true' } -try { - $MinimumLifetime = "60" #Minutes - $MaximumLifetime = "480" #minutes - $DefaultLifeTime = "60" #minutes - $DefaultLength = "8" - $body = @" - {"@odata.type":"#microsoft.graph.temporaryAccessPassAuthenticationMethodConfiguration", - "id":"TemporaryAccessPass", - "includeTargets":[{"id":"all_users", - "isRegistrationRequired":false, - "targetType":"group","displayName":"All users"}], - "defaultLength":$DefaultLength, - "defaultLifetimeInMinutes":$DefaultLifeTime, - "isUsableOnce": $TAPConfig, - "maximumLifetimeInMinutes":$MaximumLifetime, - "minimumLifetimeInMinutes":$MinimumLifetime, - "state":"enabled"} -"@ - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationmethodspolicy/authenticationMethodConfigurations/TemporaryAccessPass" -Type patch -asApp $true -Body $body -ContentType "application/json") - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled Temporary Access Passwords." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable TAP. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_TransportRuleTemplate/function.json b/Standards_TransportRuleTemplate/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_TransportRuleTemplate/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_TransportRuleTemplate/run.ps1 b/Standards_TransportRuleTemplate/run.ps1 deleted file mode 100644 index 5b29a2e6934a..000000000000 --- a/Standards_TransportRuleTemplate/run.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -param($tenant) - - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.TransportRuleTemplate -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.TransportRuleTemplate -} - -foreach ($Template in $Setting.TemplateList) { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$($Template.value)'" - $RequestParams = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet "Get-TransportRule" -useSystemMailbox $true | Where-Object -Property Identity -EQ $RequestParams.name - - - try { - if ($Existing) { - Write-Host "Found existing" - $RequestParams | Add-Member -NotePropertyValue $RequestParams.name -NotePropertyName Identity - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "Set-TransportRule" -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty UseLegacyRegex) -useSystemMailbox $true - Write-LogMessage -API "Standards" -tenant $tenant -message "Successfully set transport rule for $tenant" -sev "Info" - } - else { - Write-Host "Creating new" - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "New-TransportRule" -cmdParams $RequestParams -useSystemMailbox $true - Write-LogMessage -API "Standards" -tenant $tenant -message "Successfully created transport rule for $tenant" -sev "Info" - } - - Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($tenantfilter)" -sev "Debug" - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not create transport rule for $($tenantfilter): $($_.Exception.message)" -sev "Error" - } -} \ No newline at end of file diff --git a/Standards_UndoOauth/function.json b/Standards_UndoOauth/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_UndoOauth/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_UndoOauth/run.ps1 b/Standards_UndoOauth/run.ps1 deleted file mode 100644 index cdf054417241..000000000000 --- a/Standards_UndoOauth/run.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -param($tenant) -try { - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["ManagePermissionGrantsForSelf.microsoft-user-default-legacy"]}' -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Application Consent Mode has been disabled." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set Application Consent Mode to disabled Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_UndoSSPR/function.json b/Standards_UndoSSPR/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_UndoSSPR/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_UndoSSPR/run.ps1 b/Standards_UndoSSPR/run.ps1 deleted file mode 100644 index b6c0c198165a..000000000000 --- a/Standards_UndoSSPR/run.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -param($tenant) -Write-LogMessage -API "Standards" -tenant $tenant -message "The standard for SSPR is no longer supported." -sev Error diff --git a/Standards_UserSubmissions/function.json b/Standards_UserSubmissions/function.json deleted file mode 100644 index e498538b37c5..000000000000 --- a/Standards_UserSubmissions/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} diff --git a/Standards_UserSubmissions/run.ps1 b/Standards_UserSubmissions/run.ps1 deleted file mode 100644 index 70b961c87ea6..000000000000 --- a/Standards_UserSubmissions/run.ps1 +++ /dev/null @@ -1,44 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.usersubmissions -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.usersubmissions -} -if ($Setting.enable -and $Setting.disable) { - Write-LogMessage -API "Standards" -tenant $tenant -message "You cannot both enable and disable the User Submission policy" -sev Error - Exit -} -elseif ($setting.enable) { - $status = $true - try { - $Policy = New-ExoRequest -tenantid $Tenant -cmdlet "Get-ReportSubmissionPolicy" - if ($Policy.length -eq 0) { - New-ExoRequest -tenantid $Tenant -cmdlet "New-ReportSubmissionPolicy" - Write-LogMessage -API "Standards" -tenant $tenant -message "User Submission policy set to $status." -sev Info - } - else { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-ReportSubmissionPolicy" -cmdParams @{ EnableReportToMicrosoft = $status; Identity = $($Policy.Identity); } - Write-LogMessage -API "Standards" -tenant $tenant -message "User Submission policy set to $status." -sev Info - } - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set User Submission policy to $status. Error: $($_.exception.message)" -sev Error - } -} -else { - $status = $false - try { - $Policy = New-ExoRequest -tenantid $Tenant -cmdlet "Get-ReportSubmissionPolicy" - if ($Policy.length -eq 0) { - Write-LogMessage -API "Standards" -tenant $tenant -message "User Submission policy set to $status." -sev Info - } - else { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-ReportSubmissionPolicy" -cmdParams @{ EnableReportToMicrosoft = $status; Identity = $($Policy.Identity); EnableThirdPartyAddress = $status; ReportJunkToCustomizedAddress = $status; ReportNotJunkToCustomizedAddress = $status; ReportPhishToCustomizedAddress = $status; } - Write-LogMessage -API "Standards" -tenant $tenant -message "User Submission policy set to $status." -sev Info - } - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set User Submission policy to $status. Error: $($_.exception.message)" -sev Error - } -} \ No newline at end of file diff --git a/Standards_allowOAuthTokens/function.json b/Standards_allowOAuthTokens/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_allowOAuthTokens/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_allowOAuthTokens/run.ps1 b/Standards_allowOAuthTokens/run.ps1 deleted file mode 100644 index 7b18fd438449..000000000000 --- a/Standards_allowOAuthTokens/run.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -param($tenant) - -try { - - $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath" -tenantid $Tenant - $CurrentInfo.state = "enabled" - $body = ($CurrentInfo | ConvertTo-Json -Depth 10) - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath" -Type patch -Body $body -ContentType "application/json") - - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled software OTP/oAuth tokens" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable software OTP/oAuth tokens. Error: $($_.exception.message)" -sev "Error" -} \ No newline at end of file diff --git a/Standards_allowOTPTokens/function.json b/Standards_allowOTPTokens/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_allowOTPTokens/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_allowOTPTokens/run.ps1 b/Standards_allowOTPTokens/run.ps1 deleted file mode 100644 index 6344508da742..000000000000 --- a/Standards_allowOTPTokens/run.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -param($tenant) - -try { - - $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -tenantid $Tenant - $CurrentInfo.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') - $CurrentInfo.isSoftwareOathEnabled = $true - $body = ($CurrentInfo | ConvertTo-Json -Depth 10) - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") - - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled MS authenticator OTP/oAuth tokens" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable MS authenticator OTP/oAuth tokens. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_calDefault/function.json b/Standards_calDefault/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_calDefault/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_calDefault/run.ps1 b/Standards_calDefault/run.ps1 deleted file mode 100644 index f2e54d38773a..000000000000 --- a/Standards_calDefault/run.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.caldefault -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.caldefault -} - - -$Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet "get-mailbox" -foreach ($Mailbox in $Mailboxes) { - try { - New-ExoRequest -tenantid $Tenant -cmdlet "Get-MailboxFolderStatistics" -cmdParams @{identity = $Mailbox.UserPrincipalName; FolderScope = 'Calendar' } -Anchor $Mailbox.UserPrincipalName | Where-Object { $_.FolderType -eq 'Calendar' } | ForEach-Object { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-MailboxFolderPermission" -cmdparams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $setting.permissionlevel } -Anchor $Mailbox.UserPrincipalName - Write-LogMessage -API "Standards" -tenant $tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $($setting.permissionlevel)" -sev Info - } - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($_.exception.message)" -sev Error - } - -} -Write-LogMessage -API "Standards" -tenant $tenant -message "Done setting default calendar permissions." -sev Info \ No newline at end of file diff --git a/Standards_disableMacSync/function.json b/Standards_disableMacSync/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_disableMacSync/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_disableMacSync/run.ps1 b/Standards_disableMacSync/run.ps1 deleted file mode 100644 index 232e6be61387..000000000000 --- a/Standards_disableMacSync/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -param($tenant) - -try { - $body = '{"isMacSyncAppEnabled": false}' - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/sharepoint/settings" -AsApp $true -Type patch -Body $body -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled Mac OneDrive Sync" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable Mac OneDrive Sync: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_fwdAdminAlerts/function.json b/Standards_fwdAdminAlerts/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_fwdAdminAlerts/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_fwdAdminAlerts/run.ps1 b/Standards_fwdAdminAlerts/run.ps1 deleted file mode 100644 index fa5add33f029..000000000000 --- a/Standards_fwdAdminAlerts/run.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.caldefault -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.caldefault -} - - -$Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet "get-mailbox" -foreach ($Mailbox in $Mailboxes) { - try { - New-ExoRequest -tenantid $Tenant -cmdlet "Get-MailboxFolderStatistics" -cmdParams @{identity = $Mailbox.UserPrincipalName; FolderScope = 'Calendar' } -Anchor $Mailbox.UserPrincipalName | ForEach-Object { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-MailboxFolderPermission" -cmdparams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $setting.permissionlevel } -Anchor $Mailbox.UserPrincipalName - Write-LogMessage -API "Standards" -tenant $tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $($setting.permissionlevel)" -sev Info - } - } - catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($_.exception.message)" -sev Error - } - -} -Write-LogMessage -API "Standards" -tenant $tenant -message "Done setting default calendar permissions." -sev Info \ No newline at end of file diff --git a/Standards_intuneDeviceReg/function.json b/Standards_intuneDeviceReg/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_intuneDeviceReg/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_intuneDeviceReg/run.ps1 b/Standards_intuneDeviceReg/run.ps1 deleted file mode 100644 index 20cff265909a..000000000000 --- a/Standards_intuneDeviceReg/run.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -param($tenant) -try { - $ConfigTable = Get-CippTable -tablename 'standards' - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.intuneDeviceReg - if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.intuneDeviceReg - } - $PreviousSetting = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy" -tenantid $Tenant - $PreviousSetting.userDeviceQuota = $Setting.max - $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy" -Type PUT -Body $NewBody -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Set user device quota to $($setting.max)" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set user device quota to $($setting.max) : $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_intuneDeviceRetirementDays/function.json b/Standards_intuneDeviceRetirementDays/function.json deleted file mode 100644 index 2d4ea9094b24..000000000000 --- a/Standards_intuneDeviceRetirementDays/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "direction": "in", - "type": "activityTrigger" - } - ] -} \ No newline at end of file diff --git a/Standards_intuneDeviceRetirementDays/run.ps1 b/Standards_intuneDeviceRetirementDays/run.ps1 deleted file mode 100644 index 2ff61cc18f3e..000000000000 --- a/Standards_intuneDeviceRetirementDays/run.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.DeviceInactivityBeforeRetirementInDays -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.DeviceInactivityBeforeRetirementInDays -} - -try { - - $body = @{ DeviceInactivityBeforeRetirementInDays = $Setting.days } | ConvertTo-Json - - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupSettings" -Type PATCH -Body $body -ContentType "application/json") - - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled DeviceInactivityBeforeRetirementInDays." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable DeviceInactivityBeforeRetirementInDays. Error: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_intuneRequireMFA/function.json b/Standards_intuneRequireMFA/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_intuneRequireMFA/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_intuneRequireMFA/run.ps1 b/Standards_intuneRequireMFA/run.ps1 deleted file mode 100644 index 445ab1fee6ac..000000000000 --- a/Standards_intuneRequireMFA/run.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -param($tenant) -try { - $PreviousSetting = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy" -tenantid $Tenant - $PreviousSetting.multiFactorAuthConfiguration = '1' - $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy" -Type PUT -Body $NewBody -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Set required to use MFA when joining Intune Devices" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set require to use MFA when joining Intune Devices: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_laps/function.json b/Standards_laps/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_laps/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_laps/run.ps1 b/Standards_laps/run.ps1 deleted file mode 100644 index 7aeedfe9124f..000000000000 --- a/Standards_laps/run.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -param($tenant) -try { - $PreviousSetting = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy" -tenantid $Tenant - $previoussetting.localadminpassword.isEnabled = $true - $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy" -Type PUT -Body $newBody -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "LAPS has been enabled." -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set LAPS: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_sharingCapability/function.json b/Standards_sharingCapability/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_sharingCapability/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_sharingCapability/run.ps1 b/Standards_sharingCapability/run.ps1 deleted file mode 100644 index 746f067723f5..000000000000 --- a/Standards_sharingCapability/run.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -param($tenant) - -$ConfigTable = Get-CippTable -tablename 'standards' -$Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.sharingCapability -if (!$Setting) { - $Setting = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.sharingCapability -} - -try { - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/sharepoint/settings" -AsApp $true -Type patch -Body "{`"sharingCapability`":`"$($Setting.Level)`"}" -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Set sharing level to $($Setting.level)" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set sharing level to $($Setting.level): $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/Standards_unmanagedSync/function.json b/Standards_unmanagedSync/function.json deleted file mode 100644 index ce713ef7d4f6..000000000000 --- a/Standards_unmanagedSync/function.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bindings": [ - { - "name": "tenant", - "type": "activityTrigger", - "direction": "in" - } - ] -} \ No newline at end of file diff --git a/Standards_unmanagedSync/run.ps1 b/Standards_unmanagedSync/run.ps1 deleted file mode 100644 index a46d1bc146f5..000000000000 --- a/Standards_unmanagedSync/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -param($tenant) - -try { - $body = '{"isUnmanagedSyncAppForTenantRestricted": false}' - New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/admin/sharepoint/settings" -AsApp $true -Type patch -Body $body -ContentType "application/json" - Write-LogMessage -API "Standards" -tenant $tenant -message "Disabled Sync for unmanaged devices" -sev Info -} -catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to disable Sync for unmanaged devices: $($_.exception.message)" -sev Error -} \ No newline at end of file diff --git a/host.json b/host.json index c35d7ceb5451..ee3245a61b88 100644 --- a/host.json +++ b/host.json @@ -8,8 +8,11 @@ "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[2.*, 3.0.0)" }, - "extensions": {}, + "extensions": { + "queues": { + "maxDequeueCount": 5 + }}, "logging": { "fileLoggingMode": "never" - } + } } diff --git a/profile.ps1 b/profile.ps1 index 66e78cec4b1c..5b932cfda949 100644 --- a/profile.ps1 +++ b/profile.ps1 @@ -11,15 +11,16 @@ # Authenticate with Azure PowerShell using MSI. # Remove this if you are not planning on using MSI or Azure PowerShell. -Import-Module CippCore -try { - Import-Module Az.KeyVault -ErrorAction Stop -} catch { $_.Exception.Message } -try { - Import-Module Az.Accounts -} catch { $_.Exception.Message } -Import-Module CippExtensions +# Import modules +@('CippCore','CippExtensions','Az.KeyVault','Az.Accounts') | ForEach-Object { + try { + Import-Module -Name $_ -ErrorAction Stop + } catch { + Write-LogMessage -message "Failed to import module $($_): $_.Exception.Message" -Sev 'CRITICAL' + $_.Exception.Message + } +} try { Disable-AzContextAutosave -Scope Process | Out-Null @@ -37,4 +38,4 @@ try { # Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell. # Enable-AzureRmAlias -# You can also define functions or aliases that can be referenced in any of your PowerShell functions. \ No newline at end of file +# You can also define functions or aliases that can be referenced in any of your PowerShell functions. diff --git a/version_latest.txt b/version_latest.txt index 5ca7df98c441..490375502c2a 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -4.7.4 \ No newline at end of file +4.8.4 \ No newline at end of file