├── .gitignore ├── CONTRIBUTING.md ├── Custom Configurations └── CustomConfigurations.json ├── Deprecated └── dotnet │ ├── README.md │ └── cbcm-csharp │ ├── .vs │ └── cbcm-csharp │ │ ├── CopilotIndices │ │ └── 17.14.827.52834 │ │ │ ├── CodeChunks.db │ │ │ └── SemanticSymbols.db │ │ └── v17 │ │ ├── .suo │ │ └── DocumentLayout.json │ ├── cbcm-csharp.sln │ ├── cbcmApp │ ├── App.config │ ├── ConfigHelper.cs │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── cbcmApp.csproj │ ├── cbcmApp.csproj.user │ └── obj │ │ ├── Debug │ │ ├── .NETFramework,Version=v4.7.2.AssemblyAttributes.cs │ │ └── cbcmApp.csproj.AssemblyReference.cache │ │ └── Release │ │ ├── .NETFramework,Version=v4.7.2.AssemblyAttributes.cs │ │ └── cbcmApp.csproj.AssemblyReference.cache │ ├── cbcmClient │ ├── AuthorizationToken.cs │ ├── BaseHelper.cs │ ├── CBCMEnrollmentToken.cs │ ├── ChromeBrowser.cs │ ├── ChromeMgmtPolicy.cs │ ├── ChrometPolicyResolve.cs │ ├── DirectoryOrgUnit.cs │ ├── ExtensionDetails.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── cbcmClient.csproj │ ├── obj │ │ ├── Debug │ │ │ ├── .NETFramework,Version=v4.7.2.AssemblyAttributes.cs │ │ │ └── cbcmClient.csproj.AssemblyReference.cache │ │ └── Release │ │ │ ├── .NETFramework,Version=v4.7.2.AssemblyAttributes.cs │ │ │ └── cbcmClient.csproj.AssemblyReference.cache │ └── packages.config │ └── cbcmschema │ ├── BrowserAnnotatedItem.cs │ ├── BrowserDevices.cs │ ├── BrowserPolicyRequest.cs │ ├── ChromeMgmtPolicy.cs │ ├── CrxcavatorRiskItem.cs │ ├── EnrollmentTokenItem.cs │ ├── ExtensionInstallDeviceReport.cs │ ├── ExtensionInstallReport.cs │ ├── ExtensionItem.cs │ ├── ExtensionMgmtPolicy.cs │ ├── MoveChromeBrowsersToOu.cs │ ├── OrgUnits.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── ResponseException.cs │ ├── SpinRiskItem.cs │ ├── cbcmSchema.csproj │ ├── obj │ ├── Debug │ │ ├── .NETFramework,Version=v4.7.2.AssemblyAttributes.cs │ │ └── cbcmSchema.csproj.AssemblyReference.cache │ └── Release │ │ ├── .NETFramework,Version=v4.7.2.AssemblyAttributes.cs │ │ └── cbcmSchema.csproj.AssemblyReference.cache │ └── packages.config ├── LICENSE ├── Python ├── BlockExtensionBasedOnRiskScore.py ├── BlockExtensionBasedOnRiskScoreOutput.png ├── README.md ├── cbcm-browser-basic-export.py ├── cbcm-browser-extension-profile-export-Capture.PNG ├── cbcm-browser-extension-profile-export.py ├── cbcm-device-gbp-create.py ├── cbcm-profiles-export.py ├── cloudidentitymembership.py ├── connectors │ └── splunk │ │ ├── README.md │ │ ├── cbcm │ │ ├── README │ │ │ ├── alert_actions.conf.spec │ │ │ └── savedsearches.conf.spec │ │ ├── appserver │ │ │ └── static │ │ │ │ └── app_icon.png │ │ ├── bin │ │ │ ├── README │ │ │ ├── cbcm.py │ │ │ └── import_declare_test.py │ │ ├── default │ │ │ ├── alert_actions.conf │ │ │ ├── app.conf │ │ │ └── data │ │ │ │ └── ui │ │ │ │ ├── alerts │ │ │ │ └── cbcm.html │ │ │ │ ├── nav │ │ │ │ └── default.xml │ │ │ │ └── views │ │ │ │ └── README │ │ └── metadata │ │ │ └── default.meta │ │ └── screenshot │ │ └── lib.png ├── extension_query.py ├── extension_query_py2.py └── extension_query_sample.png ├── README.md ├── Windows ├── PinChromeToTaskbar.xml ├── PowerShell │ ├── CommandAs │ │ └── WakeBrowserAsSystem.ps1 │ ├── Delete-ChromeRegistry.ps1 │ ├── ForceUpdateBrowser.ps1 │ ├── MoveBookmarksBetweenProfiles.ps1 │ ├── README.md │ ├── Unenroll-from-CBCM.cmd │ ├── WakeBrowser.ps1 │ ├── cbcm │ │ ├── AddEnrollmentTokenThenRegister.ps1 │ │ ├── CommandAs │ │ │ └── AddEnrollmentTokenThenRegisterAsSystem.ps1 │ │ ├── MoveEnrolledBrowserByWindowsOSName.ps1 │ │ ├── MoveReEnrollBrowser.ps1 │ │ ├── README.md │ │ ├── UnenrollBrowser.ps1 │ │ ├── cbcm_get_token_with_json_file.ps1 │ │ └── cbcm_get_token_with_json_var.ps1 │ ├── disableEdgeDefaultBrowserSettingsCampaigns.ps1 │ ├── unenroll-admin-cmd-capture.PNG │ └── update3web_demo.js └── README.md ├── curl └── authorization.md ├── docs ├── API_Get_Started.md ├── App_Details_api.md ├── CBCM_api.md ├── Chrome_Management_Reports_api.md ├── Chrome_Policy_api.md ├── Directory_api.md ├── Enrollment_Token_api.md ├── ExtensionRiskSignals_FromImport.PNG ├── ExtensionRiskSignals_FromOU.PNG ├── Reports_api.md ├── auth.md ├── create_proj.MD ├── create_project.md ├── images │ ├── OAuthConsentProcess.svg │ ├── blank.md │ ├── consent_screen_1.png │ ├── consent_screen_scope.png │ └── oAuth_Cred_Create.PNG ├── policy_examples │ ├── com.google.Chrome.plist │ ├── initial_preferences │ ├── managed_policies.json │ ├── policies.reg │ └── recommended_policies.json ├── proj_apis.MD ├── service_acct.MD └── start.md ├── mobile └── ChromeBrowserCloudManagement.mobileconfig └── postman └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | "" 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement (CLA). You (or your employer) retain the copyright to your 10 | contribution; this simply gives us permission to use and redistribute your 11 | contributions as part of the project. Head over to 12 | to see your current agreements on file or 13 | to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code Reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult 23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 24 | information on using pull requests. 25 | 26 | ## Community Guidelines 27 | 28 | This project follows 29 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 30 | -------------------------------------------------------------------------------- /Custom Configurations/CustomConfigurations.json: -------------------------------------------------------------------------------- 1 | { 2 | "ExtensionSettings": { 3 | "*": { 4 | "blocked_install_message": "Please contact the IT Service Desk for more information and next steps" 5 | }, 6 | "akimgimeeoiognljlfchpbkpfbmeapkh": { 7 | "installation_mode": "normal_installed", 8 | "update_url": "https://clients2.google.com/service/update2/crx" 9 | }, 10 | "aapbdbdomjkkjkaonfhkkikfgjllcleb": { 11 | "installation_mode": "removed" 12 | }, 13 | "blipmdconlkpinefehnmjammfjpmpbjk": { 14 | "blocked_install_message": "Lighthouse is not alllowed for the Sales team.", 15 | "installation_mode": "blocked" 16 | } 17 | }, 18 | "AutoLaunchProtocolsFromOrigins": [ 19 | { 20 | "allowed_origins": [ 21 | "https://example.com" 22 | ], 23 | "protocol": "spotify" 24 | } 25 | ], 26 | "ProxySettings": { 27 | "ProxyMode": "system" 28 | }, 29 | "LensOverlaySettings": 1, 30 | "DownloadDirectory": "/home/${user_name}/Downloads", 31 | "HomepageIsNewTabPage": false, 32 | "HomepageLocation": "https://www.chromium.org/chromium-projects/", 33 | "RestoreOnStartup": 4, 34 | "RestoreOnStartupURLs": [ 35 | "https://www.chromium.org/chromium-projects/" 36 | ], 37 | "ShowHomeButton": false, 38 | "CloudPrintProxyEnabled": false, 39 | "RemoteAccessHostAllowClientPairing": false, 40 | "RemoteAccessHostAllowGnubbyAuth": false, 41 | "recommended": [ 42 | "DownloadDirectory", 43 | "HomepageIsNewTabPage", 44 | "HomepageLocation", 45 | "RestoreOnStartup", 46 | "RestoreOnStartupURLs", 47 | "ShowHomeButton" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /Deprecated/dotnet/README.md: -------------------------------------------------------------------------------- 1 | # CBCM-CSharp (C#) 2 | cbcm-csharp is a [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) .NET Framework solution written to demonstrate the use of CBCM APIs. You can use it to learn, create, and solve complex use cases through automation and integration. 3 | 4 | ## Building the site :building_construction: 5 | You will need a recent version of [Visual Studio](https://visualstudio.microsoft.com/). 6 | 7 | ### config 8 | Before buidling the solution, remember to modify the app.config file. 9 | ```xml 10 | "account_key_file": "Service Account Key File.json", 11 | "customer_id": "Customer ID. You can find by navigating to your Google Admin Console instance > Account > Account Settings.", 12 | "adminUserToImpersonate": "If you configured domain wide delegation (DwD), then you will have to provide admin/delegated admin account name." 13 | ``` 14 | 15 | ## CBCM App :computer: 16 | After you build the solution, you can run cbcmApp.exe from the Windows command prompt using various arguments. 17 | 18 | ### Get All Organizational Units (OU) 19 | ``` 20 | { 21 | "Argument": 2, 22 | "Usage": "cbcmapp.exe 2", 23 | "Output": "CBCM_DirectoryOrgUnit.csv" 24 | } 25 | ``` 26 | ### Find enrolled browsers with missing data (profile, extensions, and policies) 27 | ``` 28 | { 29 | "Argument": 3, 30 | "Usage": "cbcmapp.exe 3", 31 | "Output": "CBCM_BrowsersWithMissingData.csv" 32 | } 33 | ``` 34 | ### Find browsers installed on the user's app data folder. Applies to Windows OS platform only 35 | ``` 36 | { 37 | "Argument": 4, 38 | "Usage": "cbcmapp.exe 4", 39 | "Output": "CBCM_BrowserDevicesInstalledOnUserAppDataFolder.csv" 40 | } 41 | ``` 42 | 43 | ### Move Chrome browser Devices between Organization Units 44 | ``` 45 | { 46 | "Argument": "6" "OU Path" "machine names csvtxt file" 47 | "Usage": cbcmapp.exe 6 "/APAC/Tokyo" "C:/Temp/MoveDevices.[csv|txt]" 48 | "Output": "moveChromeBrowsersToOu.txt" 49 | } 50 | ``` 51 | ### Backup policies for an Organizational Unit (OU) 52 | ``` 53 | { 54 | "Argument": "20" "OU ID" 55 | "Usage": cbcmapp.exe 20 "03phkw8rsq" 56 | "Output": "policybackup.json" 57 | } 58 | ``` 59 | ### Get all enrolled browser data with an optional argument to query by orgnizational unit (demo purpose) 60 | :exclamation: Note: the recommended approach is to fast-write to a data store. In this sample code it writes to the local disk. 61 | {deviceId,machineName,orgUnitPath,lastDeviceUser,lastActivityTime,serialNumber,osPlatform,osArchitecture,osVersion,policyCount,machinePolicies,extensionCount,extensionId,extensionName} 62 | ``` 63 | { 64 | "Argument": "100" "OU Path" 65 | "Usage": cbcmapp.exe 100 "/APAC/Tokyo" 66 | "Usage": cbcmapp.exe 100 67 | "Output": "all-enrolled-browser-data.csv" 68 | } 69 | ``` 70 | ### Get basic enrolled browser data with an optional argument to query by orgnizational unit. 71 | Output columns {deviceId,machineName,orgUnitPath,lastDeviceUser,lastActivityTime,serialNumber,osPlatform,osArchitecture,osVersion,policyCount,extensionCount} 72 | ``` 73 | { 74 | "Argument": "101" "OU Path" 75 | "Usage": cbcmapp.exe 101 "/APAC/Tokyo" 76 | "Output": "all-enrolled-browser-data.csv" 77 | } 78 | ``` 79 | 80 | ### Extensions 81 | #### Download extensions installed in your enterprise with 3rd party risk scores from [CRXcavator](https://crxcavator.io/) and [Spin.ai](https://spin.ai/platform/google-workspace/apps-security/) 82 | ``` 83 | { 84 | "Argument": "300" OU ID (optional) 85 | "Usage": cbcmapp.exe 300 03phkw8rsq 86 | "Output": "ExtensionRiskSignals_[OU ID].csv" 87 | } 88 | ``` 89 | Sample output 90 | 91 |  92 | 93 | #### Download 3rd party risk scores from [CRXcavator](https://crxcavator.io/) and [Spin.ai](https://spin.ai/platform/google-workspace/apps-security/) for {extension,version} input data 94 | ``` 95 | { 96 | "Argument": "301" file path 97 | "Usage": cbcmapp.exe 301 extensionsignalimport.txt 98 | "Output": "ExtensionRiskSignals_FromImport.csv" 99 | } 100 | ``` 101 | Sample input 102 | ``` 103 | aapbdbdomjkkjkaonfhkkikfgjllcleb 104 | blipmdconlkpinefehnmjammfjpmpbjk 105 | mclkkofklkfljcocdinagocijmpgbhab,10.2.0.2 106 | lpcaedmchfhocbbapmcbpinfpgnhiddi, 4.22452.1312.1 107 | ldipcbpaocekfooobnbcddclnhejkcpn , 3.2 108 | hkgfoiooedgoejojocmhlaklaeopbecg,1.11 109 | ``` 110 | Sample output 111 | 112 |  113 | 114 | ### Generate report to find devices that have extension(s) installed 115 | ``` 116 | { 117 | "Argument": 302 extension Id 118 | "Argument": 303 file containing extension Ids.txt 119 | "Usage": 302 mefhakmgclhhfbdadeojlkbllmecialg 120 | "Usage": 303 findinstalledAppDevices.txt 121 | "Output": CSV file containing appId,deviceId,machine 122 | } 123 | ``` 124 | 125 | ### Bulk upload extension IDs to an OU with install policy 126 | ``` 127 | { 128 | "Argument": "5" "OU ID" "Install Policy (ALLOWED, BLOCKED, FORCED)" "extensions ID csv/txt file", 129 | "Usage": cbcmapp.exe 5 "03phkw8rsq" "BLOCKED" "C:/Temp/BatchUploadExtensions.[csv|txt]", 130 | "Output": "BatchUploadExtensionsToOu.txt" 131 | } 132 | ``` 133 | 134 | ### Inactive Browser 135 | #### Find browsers in an Organizational Unit (OU) where the last activity date is between given start and end days (format yyyy-MM-dd) 136 | ``` 137 | { 138 | "Argument": "800" "OU Path" "Start date" "End date" 139 | "Usage sample 1": cbcmapp.exe 800 "/North America/Algonquin" "2022-01-01" "2022-04-01" 140 | "Usage sample 2": cbcmapp.exe 800 "" "2022-01-01" "2022-04-01" 141 | "Output": "CBCM_BrowsersFilteredByLastActivityDate.csv" 142 | } 143 | ``` 144 | #### Move inactive browsers to an OU 145 | ``` 146 | { 147 | "Argument": "810" "Source OU Path" "Destination OU Path" The number of days to specify to determine the inactive date. Optional query filter, find all devices with machine name that contain the "vdi" word **machine_name:vdi**. 148 | "Usage": cbcmapp.exe 810 "/Managed Browser" "/Managed Browser/Inactive Devices" 30 "machine_name:vdi" 149 | "Output": "MoveInactiveBrowsers.txt" 150 | } 151 | ``` 152 | #### Move active browsers to an OU 153 | ``` 154 | { 155 | "Argument": "820" "Source OU Path" "Destination OU Path" The number of days to specify to determine the active date. Optional query filter, find all devices with machine name that contain the "vdi" word **machine_name:vdi**. 156 | "Usage": cbcmapp.exe 820 "/North America/Austin/AUS Inactive Browsers" "/North America/Austin/AUS Managed Browser" 1 157 | "Output": "MoveActiveBrowsers.txt" 158 | } 159 | ``` 160 | 161 | #### Delete inactive browser in an Organizational Unit (OU). 162 | ``` 163 | { 164 | "Argument": "890" "OU Path" The number of days to specify to determine the inactive date. Query filter, find all devices with machine name that contain the "vdi" word **machine_name:vdi**. 165 | "Usage sample 1": cbcmapp.exe 890 "/Managed Browser/Inactive Devices" 29 "machine_name:vdi" 166 | "Output": none 167 | } 168 | ``` 169 | ### Delete Enrolled Browser 170 | #### Delete enrolled browsers from the admin console. Input file must contain a comma-separated list of machine names. 171 | ``` 172 | { 173 | "Argument": "990" "machine names csv file" 174 | "Usage": cbcmapp.exe 990 "C:/Temp/deleteBrowsers.csv" 175 | "Output": "deleteChromeBrowsers.csv" 176 | } 177 | ``` 178 | #### Delete enrolled browsers from the admin console. Input file must contain a comma-separated list of deviceIds. 179 | ``` 180 | { 181 | "Argument": "991" "deviceId csv file" 182 | "Usage": cbcmapp.exe 991 "C:/Temp/deleteBrowsers.csv" 183 | "Output": "deleteChromeBrowsers.csv" 184 | } 185 | ``` 186 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/.vs/cbcm-csharp/CopilotIndices/17.14.827.52834/CodeChunks.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/.vs/cbcm-csharp/CopilotIndices/17.14.827.52834/CodeChunks.db -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/.vs/cbcm-csharp/CopilotIndices/17.14.827.52834/SemanticSymbols.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/.vs/cbcm-csharp/CopilotIndices/17.14.827.52834/SemanticSymbols.db -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/.vs/cbcm-csharp/v17/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/.vs/cbcm-csharp/v17/.suo -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/.vs/cbcm-csharp/v17/DocumentLayout.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 1, 3 | "WorkspaceRootPath": "C:\\Users\\nsamarakkody\\source\\repos\\ChromeBrowserEnterprise\\google\\ChromeBrowserEnterprise\\dotnet\\cbcm-csharp\\", 4 | "Documents": [], 5 | "DocumentGroupContainers": [ 6 | { 7 | "Orientation": 0, 8 | "VerticalTabListWidth": 256, 9 | "DocumentGroups": [ 10 | { 11 | "DockedWidth": 200, 12 | "SelectedChildIndex": -1, 13 | "Children": [ 14 | { 15 | "$type": "Bookmark", 16 | "Name": "ST:0:0:{56df62a4-05a3-4e5b-aa1a-99371ccfb997}" 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcm-csharp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32210.238 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cbcmApp", "cbcmApp\cbcmApp.csproj", "{880B1B62-7DC7-4E01-BE66-14DC2B3C66AA}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cbcmSchema", "cbcmschema\cbcmSchema.csproj", "{EAF5E83E-CBE9-4401-A644-AEEB2DF990F9}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cbcmClient", "cbcmClient\cbcmClient.csproj", "{03C9C393-DB6E-4A4B-9475-54E00BA1DFD1}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {880B1B62-7DC7-4E01-BE66-14DC2B3C66AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {880B1B62-7DC7-4E01-BE66-14DC2B3C66AA}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {880B1B62-7DC7-4E01-BE66-14DC2B3C66AA}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {880B1B62-7DC7-4E01-BE66-14DC2B3C66AA}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {EAF5E83E-CBE9-4401-A644-AEEB2DF990F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {EAF5E83E-CBE9-4401-A644-AEEB2DF990F9}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {EAF5E83E-CBE9-4401-A644-AEEB2DF990F9}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {EAF5E83E-CBE9-4401-A644-AEEB2DF990F9}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {03C9C393-DB6E-4A4B-9475-54E00BA1DFD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {03C9C393-DB6E-4A4B-9475-54E00BA1DFD1}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {03C9C393-DB6E-4A4B-9475-54E00BA1DFD1}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {03C9C393-DB6E-4A4B-9475-54E00BA1DFD1}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {2435EBF9-BF0E-4198-8FB2-3D94C1C6711A} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/ConfigHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | 4 | namespace cbcmApp 5 | { 6 | 7 | internal sealed class ConfigHelper 8 | { 9 | private AppSettingsReader appSettingsReader = null; 10 | 11 | /// 12 | /// Service Account Key File.json 13 | /// 14 | internal string AccountKeyFile { 15 | get 16 | { 17 | return this.appSettingsReader.GetValue("account_key_file", typeof(string)).ToString(); 18 | } 19 | 20 | } 21 | /// 22 | /// Customer ID. You can find by navigating to your Google Admin Console instance > Account > Account Settings. 23 | /// 24 | internal string CustomerID 25 | { 26 | get 27 | { 28 | return this.appSettingsReader.GetValue("customer_id", typeof(string)).ToString(); 29 | } 30 | } 31 | 32 | /// 33 | /// If you configured domain wide delegation (DwD), then you will have to provide admin/delegated admin account name. 34 | /// 35 | internal string adminUserToImpersonate 36 | { 37 | get 38 | { 39 | return this.appSettingsReader.GetValue("adminUserToImpersonate", typeof(string)).ToString(); 40 | } 41 | } 42 | 43 | public ConfigHelper() 44 | { 45 | this.appSettingsReader = new AppSettingsReader(); 46 | } 47 | 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("cbcmApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Google")] 12 | [assembly: AssemblyProduct("cbcmApp")] 13 | [assembly: AssemblyCopyright("Copyright © Google 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("880b1b62-7dc7-4e01-be66-14dc2b3c66aa")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/cbcmApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {880B1B62-7DC7-4E01-BE66-14DC2B3C66AA} 8 | Exe 9 | cbcmApp 10 | cbcmApp 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {03c9c393-db6e-4a4b-9475-54e00ba1dfd1} 57 | cbcmClient 58 | 59 | 60 | {eaf5e83e-cbe9-4401-a644-aeeb2df990f9} 61 | cbcmSchema 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/cbcmApp.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] 5 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/obj/Debug/cbcmApp.csproj.AssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/cbcmApp/obj/Debug/cbcmApp.csproj.AssemblyReference.cache -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/obj/Release/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] 5 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmApp/obj/Release/cbcmApp.csproj.AssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/cbcmApp/obj/Release/cbcmApp.csproj.AssemblyReference.cache -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/AuthorizationToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace cbcmClient 8 | { 9 | public sealed class AuthorizationToken : BaseHelper 10 | { 11 | 12 | private string _customerID = String.Empty; 13 | 14 | public AuthorizationToken(string keyFile, string customerID, string adminUserToImpersonate) : base(keyFile, adminUserToImpersonate) 15 | { 16 | this._customerID = customerID; 17 | } 18 | 19 | public AuthorizationToken(string keyFile) : base(keyFile) 20 | { 21 | } 22 | 23 | public string AccessToken 24 | { 25 | get { return base.GetAuthBearerToken(); } 26 | 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/BaseHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | using Google.Apis.Auth.OAuth2; 5 | 6 | namespace cbcmClient 7 | { 8 | public class BaseHelper 9 | { 10 | //private string _keyFile = string.Empty; 11 | private string _customerID = string.Empty; 12 | protected int _timeout = 3597; //client timeout interval in seconds. 13 | protected string CustomerID { 14 | get { return String.IsNullOrEmpty(_customerID) ? "my_customer" : this._customerID; } 15 | set { this._customerID = value; } 16 | } 17 | protected string KeyFile { get; set; } 18 | 19 | protected string AdminUserToImpersonate { get; set; } 20 | 21 | private string[] _scopes = {"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly" 22 | ,"https://www.googleapis.com/auth/admin.directory.device.chromebrowsers" 23 | ,"https://www.googleapis.com/auth/chrome.management.reports.readonly" 24 | ,"https://www.googleapis.com/auth/chrome.management.appdetails.readonly" 25 | ,"https://www.googleapis.com/auth/chrome.management.policy.readonly" 26 | ,"https://www.googleapis.com/auth/chrome.management.policy" 27 | ,"https://www.googleapis.com/auth/admin.directory.orgunit.readonly" 28 | ,"https://www.googleapis.com/auth/admin.directory.orgunit" 29 | ,"https://www.googleapis.com/auth/admin.reports.audit.readonly" }; 30 | 31 | internal string LogOutputFormat = "csv"; 32 | 33 | public BaseHelper(string keyFile) 34 | { 35 | this.KeyFile = keyFile; 36 | } 37 | 38 | 39 | public BaseHelper(string keyFile, string adminUserToImpersonate) 40 | { 41 | this.KeyFile = keyFile; 42 | this.AdminUserToImpersonate = adminUserToImpersonate; 43 | } 44 | 45 | internal string GetAuthBearerToken(string[] scopes) 46 | { 47 | string bearer; 48 | GoogleCredential credential; 49 | 50 | using (Stream stream = new FileStream(this.KeyFile, FileMode.Open, FileAccess.Read, FileShare.Read)) 51 | { 52 | credential = GoogleCredential.FromStream(stream); 53 | } 54 | credential = credential.CreateScoped(scopes); 55 | //domain-wide delegation 56 | if (!String.IsNullOrEmpty(this.AdminUserToImpersonate)) 57 | credential.CreateWithUser(this.AdminUserToImpersonate); 58 | 59 | try 60 | { 61 | Task task = ((ITokenAccess)credential).GetAccessTokenForRequestAsync(); 62 | task.Wait(); 63 | bearer = task.Result; 64 | 65 | } 66 | catch (Exception ex) 67 | { 68 | throw ex; 69 | } 70 | 71 | return bearer; 72 | } 73 | 74 | internal string GetAuthBearerToken() 75 | { 76 | return this.GetAuthBearerToken(this._scopes); 77 | } 78 | 79 | internal void WriteToFile(string logFileName, string data) 80 | { 81 | string logfiilefullname = String.Format("{0}_{1}.{2}", 82 | logFileName, 83 | DateTime.Now.ToString("MM-dd-yyyy_hh-mm-ss"), 84 | this.LogOutputFormat); 85 | 86 | using (StreamWriter sw = File.AppendText(logfiilefullname)) 87 | { 88 | sw.WriteLine(data); 89 | } 90 | } 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/CBCMEnrollmentToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.IO; 5 | using System.Text; 6 | using System.Web; 7 | using RestSharp; 8 | using cbcmSchema; 9 | using cbcmSchema.EnrollmentTokenSchema; 10 | 11 | namespace cbcmClient 12 | { 13 | public sealed class CBCMEnrollmentToken : BaseHelper 14 | { 15 | #region constructor 16 | public CBCMEnrollmentToken(string keyFile, string customerID) : base(keyFile) 17 | { 18 | this.CustomerID = customerID; 19 | } 20 | 21 | public CBCMEnrollmentToken(string keyFile, string customerID, string adminUserToImpersonate) : base(keyFile, adminUserToImpersonate) 22 | { 23 | this.CustomerID = customerID; 24 | } 25 | #endregion 26 | 27 | public cbcmSchema.EnrollmentTokenSchema.ChromeEnrollmentToken FindChromeEnrollmentToken(string token) 28 | { 29 | List < cbcmSchema.EnrollmentTokenSchema.ChromeEnrollmentToken > chromeEnrollmentTokenList = this.GetAllEnrollmentToken(); 30 | cbcmSchema.EnrollmentTokenSchema.ChromeEnrollmentToken result = null; 31 | 32 | if (chromeEnrollmentTokenList == null) 33 | return null; 34 | 35 | foreach(cbcmSchema.EnrollmentTokenSchema.ChromeEnrollmentToken item in chromeEnrollmentTokenList) 36 | { 37 | if(String.Compare(token, item.Token, StringComparison.OrdinalIgnoreCase) == 0) 38 | result = item; 39 | } 40 | 41 | return result; 42 | } 43 | 44 | public List GetAllEnrollmentToken() 45 | { 46 | string nextPageToken = String.Empty; 47 | List chromeEnrollmentTokenList = new List(); 48 | string content = String.Empty; 49 | RestClient client; 50 | 51 | 52 | 53 | string[] scope = { "https://www.googleapis.com/auth/admin.directory.device.chromebrowsers" }; 54 | string token = this.GetAuthBearerToken(scope); 55 | 56 | 57 | string serviceURL = String.Format("https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/chrome/enrollmentTokens?pageSize=100&pageToken=", this.CustomerID); 58 | 59 | do 60 | { 61 | client = new RestClient(); 62 | client.Timeout = base._timeout; 63 | 64 | UriBuilder builder = new UriBuilder(serviceURL); 65 | var qs = HttpUtility.ParseQueryString(builder.Query); 66 | qs.Set("pageToken", nextPageToken); 67 | builder.Query = qs.ToString(); 68 | 69 | client.BaseUrl = builder.Uri; 70 | 71 | var request = new RestRequest(Method.GET); 72 | request.AddHeader("Content-Type", "application/json"); 73 | request.AddHeader("Authorization", String.Format("Bearer {0}", token)); 74 | IRestResponse response = client.Execute(request); 75 | 76 | if (response is null) 77 | { 78 | nextPageToken = String.Empty; 79 | continue; 80 | } 81 | 82 | content = response.Content; 83 | 84 | var chromeEnrollmentToken = cbcmSchema.EnrollmentTokenSchema.EnrollmentTokenItem.FromJson(content); 85 | 86 | //set next page token 87 | nextPageToken = chromeEnrollmentToken.NextPageToken; 88 | 89 | if (chromeEnrollmentToken.ChromeEnrollmentTokens != null) 90 | chromeEnrollmentTokenList.AddRange(chromeEnrollmentToken.ChromeEnrollmentTokens); 91 | 92 | 93 | } while (!String.IsNullOrEmpty(nextPageToken)); 94 | 95 | 96 | 97 | return chromeEnrollmentTokenList; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/ChromeMgmtPolicy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using RestSharp; 7 | using cbcmSchema.ExtensionPolicy; 8 | 9 | namespace cbcmClient 10 | { 11 | public sealed class ChromeMgmtPolicy : BaseHelper 12 | { 13 | public ChromeMgmtPolicy(string keyFile, string customerID, string adminUserToImpersonate) : base(keyFile, adminUserToImpersonate) 14 | { 15 | base.CustomerID = customerID; 16 | } 17 | 18 | public string BatchUploadExtensionsToOU(List extensionIDs, string orgUnitId, string installPolicy) 19 | { 20 | string appInstallType = this.ExtensionInstallPolicyParse(installPolicy); 21 | 22 | PolicyTargetKey policyTargetKey; 23 | PolicyValue policyValue; 24 | Value value; 25 | UpdateMask updateMask; 26 | Request request1; 27 | ExtensionMgmtPolicy extensionMgmt = new ExtensionMgmtPolicy(); 28 | List extensionInstallRequests = new List(); 29 | 30 | foreach (string extensionID in extensionIDs) 31 | { 32 | //policyTargetKey 33 | policyTargetKey = new PolicyTargetKey(); 34 | policyTargetKey.TargetResource = String.Format("orgunits/{0}", orgUnitId); 35 | AdditionalTargetKeys additionalTargetKeys = new AdditionalTargetKeys(); 36 | additionalTargetKeys.AppId = String.Format("chrome:{0}", extensionID); 37 | policyTargetKey.AdditionalTargetKeys = additionalTargetKeys; 38 | 39 | //Value 40 | value = new Value(); 41 | value.AppInstallType = appInstallType; 42 | //policyValue 43 | policyValue = new PolicyValue(); 44 | policyValue.Value = value; 45 | policyValue.PolicySchema = "chrome.users.apps.InstallType"; 46 | 47 | //updateMask 48 | updateMask = new UpdateMask(); 49 | updateMask.Paths = "appInstallType"; 50 | 51 | //requests 52 | request1 = new Request(); 53 | request1.PolicyTargetKey = policyTargetKey; 54 | request1.PolicyValue = policyValue; 55 | request1.UpdateMask = updateMask; 56 | 57 | extensionInstallRequests.Add(request1); 58 | } 59 | 60 | extensionMgmt.Requests = extensionInstallRequests; 61 | string body = extensionMgmt.ToJson(); 62 | 63 | string[] scope = { "https://www.googleapis.com/auth/chrome.management.policy" }; 64 | string serviceURL = String.Format("https://chromepolicy.googleapis.com/v1/customers/{0}/policies/orgunits:batchModify", this.CustomerID); 65 | 66 | string token = this.GetAuthBearerToken(scope); 67 | var request = new RestRequest(Method.POST); 68 | 69 | RestClient client = new RestClient(); 70 | Uri baseUrl = new Uri(serviceURL); 71 | client.BaseUrl = baseUrl; 72 | client.Timeout = -1; 73 | 74 | request.AddHeader("Content-Type", "application/json"); 75 | request.AddHeader("Authorization", String.Format("Bearer {0}", token)); 76 | 77 | request.AddParameter("application/json", body, ParameterType.RequestBody); 78 | IRestResponse response = client.Execute(request); 79 | 80 | return response.Content; 81 | } 82 | /// 83 | /// Parse the extension install policy. This implementation is better than using Enum.Parse(). 84 | /// 85 | /// Install policy 86 | /// FORCED, ALLOWED, BLOCKED. Default is ALLOWED 87 | /// 88 | private string ExtensionInstallPolicyParse(string value) 89 | { 90 | if (String.IsNullOrEmpty(value)) 91 | throw new ApplicationException("Extension install type (FORCED, ALLOWED, BLOCKED) is required."); 92 | 93 | string ucaseValue = value.Trim().ToUpper(); 94 | 95 | string forceInstall = "FORCED"; 96 | string allowInstall = "ALLOWED"; 97 | string blockInstall = "BLOCKED"; 98 | 99 | if (String.Compare(value, forceInstall, true) == 0) 100 | return forceInstall; 101 | 102 | if (String.Compare(value, blockInstall, true) == 0) 103 | return blockInstall; 104 | 105 | return allowInstall; 106 | } 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/DirectoryOrgUnit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using RestSharp; 4 | using cbcmSchema.OU; 5 | using System.Web; 6 | using System.Collections.Generic; 7 | 8 | namespace cbcmClient 9 | { 10 | /// 11 | /// https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits/ 12 | /// 13 | public sealed class DirectoryOrgUnit : BaseHelper 14 | { 15 | //private const string Scope = "https://www.googleapis.com/auth/admin.directory.orgunit"; 16 | private const string LogFileName = "CBCM_DirectoryOrgUnit.txt"; 17 | //private string _customerID = String.Empty; 18 | 19 | 20 | public DirectoryOrgUnit(string keyFile, string customerID, string adminUserToImpersonate) : base(keyFile, adminUserToImpersonate) 21 | { 22 | this.CustomerID = customerID; 23 | } 24 | 25 | 26 | public List GetOrgUnitList() 27 | { 28 | string serviceURL = String.Format("https://www.googleapis.com/admin/directory/v1/customer/{0}/orgunits?type=ALL", this.CustomerID); 29 | 30 | string token = this.GetAuthBearerToken(); 31 | 32 | RestClient client = new RestClient(serviceURL); 33 | client.Timeout = base._timeout; 34 | 35 | 36 | var request = new RestRequest(Method.GET); 37 | request.AddHeader("Content-Type", "application/json"); 38 | request.AddHeader("Authorization", String.Format("Bearer {0}", token)); 39 | IRestResponse response = client.Execute(request); 40 | 41 | var orgUnits = OrgUnits.FromJson(response.Content); 42 | List orgUnitsList = new List(); 43 | if (orgUnits != null) 44 | orgUnitsList = orgUnits.OrganizationUnits; 45 | 46 | return orgUnitsList; 47 | } 48 | 49 | public string GetAllOrganizationalUnits() 50 | { 51 | string serviceURL = String.Format("https://www.googleapis.com/admin/directory/v1/customer/{0}/orgunits?type=ALL", this.CustomerID); 52 | 53 | string token = this.GetAuthBearerToken(); 54 | 55 | RestClient client = new RestClient(serviceURL); 56 | client.Timeout = base._timeout; 57 | 58 | 59 | var request = new RestRequest(Method.GET); 60 | request.AddHeader("Content-Type", "application/json"); 61 | request.AddHeader("Authorization", String.Format("Bearer {0}", token)); 62 | IRestResponse response = client.Execute(request); 63 | 64 | var orgUnits = OrgUnits.FromJson(response.Content); 65 | 66 | base.WriteToFile(LogFileName, this.CovertToCSV(orgUnits)); 67 | 68 | return response.Content; 69 | } 70 | 71 | private string CovertToCSV(OrgUnits orgUnits) 72 | { 73 | StringBuilder stringBuilder = new StringBuilder(); 74 | 75 | //write the header 76 | stringBuilder.AppendLine("orgUnitId, name,description,orgUnitPath,parentOrgUnitId,parentOrgUnitPath"); 77 | 78 | if (orgUnits is null || orgUnits.OrganizationUnits is null) 79 | return stringBuilder.ToString(); 80 | 81 | foreach(OrganizationUnit orgUnit in orgUnits.OrganizationUnits) 82 | { 83 | stringBuilder.AppendLine(String.Format("{0},{1},{2},{3},{4},{5}", 84 | orgUnit.OrgUnitId, 85 | orgUnit.Name, 86 | orgUnit.Description, 87 | orgUnit.OrgUnitPath, 88 | orgUnit.ParentOrgUnitId, 89 | orgUnit.ParentOrgUnitPath) 90 | ); 91 | } 92 | 93 | return stringBuilder.ToString(); 94 | } 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("cbcmClient")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Google")] 12 | [assembly: AssemblyProduct("cbcmClient")] 13 | [assembly: AssemblyCopyright("Copyright © Google 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("03c9c393-db6e-4a4b-9475-54e00ba1dfd1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/cbcmClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {03C9C393-DB6E-4A4B-9475-54E00BA1DFD1} 8 | Library 9 | Properties 10 | cbcmClient 11 | cbcmClient 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\Google.Apis.1.57.0\lib\net45\Google.Apis.dll 37 | 38 | 39 | ..\packages\Google.Apis.Auth.1.57.0\lib\net461\Google.Apis.Auth.dll 40 | 41 | 42 | ..\packages\Google.Apis.Auth.1.57.0\lib\net461\Google.Apis.Auth.PlatformServices.dll 43 | 44 | 45 | ..\packages\Google.Apis.Core.1.57.0\lib\net45\Google.Apis.Core.dll 46 | 47 | 48 | ..\packages\Google.Apis.Oauth2.v2.1.57.0.1869\lib\net45\Google.Apis.Oauth2.v2.dll 49 | 50 | 51 | ..\packages\Google.Apis.1.57.0\lib\net45\Google.Apis.PlatformServices.dll 52 | 53 | 54 | ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 55 | 56 | 57 | ..\packages\RestSharp.106.12.0\lib\net452\RestSharp.dll 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | {eaf5e83e-cbe9-4401-a644-aeeb2df990f9} 85 | cbcmSchema 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] 5 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/obj/Debug/cbcmClient.csproj.AssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/cbcmClient/obj/Debug/cbcmClient.csproj.AssemblyReference.cache -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/obj/Release/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] 5 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/obj/Release/cbcmClient.csproj.AssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/cbcmClient/obj/Release/cbcmClient.csproj.AssemblyReference.cache -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmClient/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/BrowserAnnotatedItem.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.BrowserAnnotatedField; 6 | // 7 | // var browserAnnotatedItem = BrowserAnnotatedItem.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.BrowserAnnotatedField 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class BrowserAnnotatedItem 19 | { 20 | [JsonProperty("deviceId", NullValueHandling = NullValueHandling.Ignore)] 21 | public string DeviceId { get; set; } 22 | 23 | [JsonProperty("annotatedUser", NullValueHandling = NullValueHandling.Ignore)] 24 | public string AnnotatedUser { get; set; } 25 | 26 | [JsonProperty("annotatedLocation", NullValueHandling = NullValueHandling.Ignore)] 27 | public string AnnotatedLocation { get; set; } 28 | 29 | [JsonProperty("annotatedNotes", NullValueHandling = NullValueHandling.Ignore)] 30 | public string AnnotatedNotes { get; set; } 31 | 32 | [JsonProperty("annotatedAssetId", NullValueHandling = NullValueHandling.Ignore)] 33 | public string AnnotatedAssetId { get; set; } 34 | } 35 | 36 | public partial class BrowserAnnotatedItem 37 | { 38 | public static BrowserAnnotatedItem FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.BrowserAnnotatedField.Converter.Settings); 39 | } 40 | 41 | public static class Serialize 42 | { 43 | public static string ToJson(this BrowserAnnotatedItem self) => JsonConvert.SerializeObject(self, cbcmSchema.BrowserAnnotatedField.Converter.Settings); 44 | } 45 | 46 | internal static class Converter 47 | { 48 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 49 | { 50 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 51 | DateParseHandling = DateParseHandling.None, 52 | Converters = 53 | { 54 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 55 | }, 56 | }; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/BrowserPolicyRequest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.ChromeBrowserPolicyRequest; 6 | // 7 | // var browserPolicyRequest = BrowserPolicyRequest.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.ChromeBrowserPolicyRequest 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class BrowserPolicyRequest 19 | { 20 | [JsonProperty("policySchemaFilter", NullValueHandling = NullValueHandling.Ignore)] 21 | public string PolicySchemaFilter { get; set; } 22 | 23 | [JsonProperty("policyTargetKey", NullValueHandling = NullValueHandling.Ignore)] 24 | public PolicyTargetKey PolicyTargetKey { get; set; } 25 | 26 | [JsonProperty("pageSize", NullValueHandling = NullValueHandling.Ignore)] 27 | public int? PageSize { get; set; } 28 | 29 | [JsonProperty("pageToken", NullValueHandling = NullValueHandling.Ignore)] 30 | public string PageToken { get; set; } 31 | } 32 | 33 | public partial class PolicyTargetKey 34 | { 35 | [JsonProperty("targetResource", NullValueHandling = NullValueHandling.Ignore)] 36 | public string TargetResource { get; set; } 37 | } 38 | 39 | public partial class BrowserPolicyRequest 40 | { 41 | public static BrowserPolicyRequest FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.ChromeBrowserPolicyRequest.Converter.Settings); 42 | } 43 | 44 | public static class Serialize 45 | { 46 | public static string ToJson(this BrowserPolicyRequest self) => JsonConvert.SerializeObject(self, cbcmSchema.ChromeBrowserPolicyRequest.Converter.Settings); 47 | } 48 | 49 | internal static class Converter 50 | { 51 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 52 | { 53 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 54 | DateParseHandling = DateParseHandling.None, 55 | Converters = 56 | { 57 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 58 | }, 59 | }; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/ChromeMgmtPolicy.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.ChromeBrowserPolicy; 6 | // 7 | // var chromeMgmtPolicy = ChromeMgmtPolicy.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.ChromeBrowserPolicy 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class ChromeMgmtPolicy 19 | { 20 | [JsonProperty("resolvedPolicies", NullValueHandling = NullValueHandling.Ignore)] 21 | public List ResolvedPolicies { get; set; } 22 | 23 | [JsonProperty("nextPageToken", NullValueHandling = NullValueHandling.Ignore)] 24 | public string NextPageToken { get; set; } 25 | } 26 | 27 | public partial class ResolvedPolicy 28 | { 29 | [JsonProperty("targetKey", NullValueHandling = NullValueHandling.Ignore)] 30 | public Key TargetKey { get; set; } 31 | 32 | [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] 33 | public ResolvedPolicyValue Value { get; set; } 34 | 35 | [JsonProperty("sourceKey", NullValueHandling = NullValueHandling.Ignore)] 36 | public Key SourceKey { get; set; } 37 | } 38 | 39 | public partial class Key 40 | { 41 | [JsonProperty("targetResource", NullValueHandling = NullValueHandling.Ignore)] 42 | public string TargetResource { get; set; } 43 | } 44 | 45 | public partial class ResolvedPolicyValue 46 | { 47 | [JsonProperty("policySchema", NullValueHandling = NullValueHandling.Ignore)] 48 | public string PolicySchema { get; set; } 49 | 50 | [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] 51 | public object Value { get; set; } 52 | } 53 | 54 | 55 | 56 | public partial class ChromeMgmtPolicy 57 | { 58 | public static ChromeMgmtPolicy FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.ChromeBrowserPolicy.Converter.Settings); 59 | } 60 | 61 | public static class Serialize 62 | { 63 | public static string ToJson(this ChromeMgmtPolicy self) => JsonConvert.SerializeObject(self, cbcmSchema.ChromeBrowserPolicy.Converter.Settings); 64 | } 65 | 66 | internal static class Converter 67 | { 68 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 69 | { 70 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 71 | DateParseHandling = DateParseHandling.None, 72 | Converters = 73 | { 74 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 75 | }, 76 | }; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/EnrollmentTokenItem.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.EnrollmentTokenSchema; 6 | // 7 | // var enrollmentTokenItem = EnrollmentTokenItem.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.EnrollmentTokenSchema 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class EnrollmentTokenItem 19 | { 20 | [JsonProperty("kind", NullValueHandling = NullValueHandling.Ignore)] 21 | public string Kind { get; set; } 22 | 23 | [JsonProperty("chromeEnrollmentTokens", NullValueHandling = NullValueHandling.Ignore)] 24 | public List ChromeEnrollmentTokens { get; set; } 25 | 26 | [JsonProperty("nextPageToken", NullValueHandling = NullValueHandling.Ignore)] 27 | public string NextPageToken { get; set; } 28 | } 29 | 30 | public partial class ChromeEnrollmentToken 31 | { 32 | [JsonProperty("tokenPermanentId", NullValueHandling = NullValueHandling.Ignore)] 33 | public string TokenPermanentId { get; set; } 34 | 35 | [JsonProperty("kind", NullValueHandling = NullValueHandling.Ignore)] 36 | public string Kind { get; set; } 37 | 38 | [JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)] 39 | public string Token { get; set; } 40 | 41 | [JsonProperty("customerId", NullValueHandling = NullValueHandling.Ignore)] 42 | public string CustomerId { get; set; } 43 | 44 | [JsonProperty("orgUnitPath", NullValueHandling = NullValueHandling.Ignore)] 45 | public string OrgUnitPath { get; set; } 46 | 47 | [JsonProperty("state", NullValueHandling = NullValueHandling.Ignore)] 48 | public string State { get; set; } 49 | 50 | [JsonProperty("createTime", NullValueHandling = NullValueHandling.Ignore)] 51 | public DateTimeOffset? CreateTime { get; set; } 52 | 53 | [JsonProperty("creatorId", NullValueHandling = NullValueHandling.Ignore)] 54 | public string CreatorId { get; set; } 55 | 56 | [JsonProperty("tokenType", NullValueHandling = NullValueHandling.Ignore)] 57 | public string TokenType { get; set; } 58 | } 59 | 60 | public partial class EnrollmentTokenItem 61 | { 62 | public static EnrollmentTokenItem FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.EnrollmentTokenSchema.Converter.Settings); 63 | } 64 | 65 | public static class Serialize 66 | { 67 | public static string ToJson(this EnrollmentTokenItem self) => JsonConvert.SerializeObject(self, cbcmSchema.EnrollmentTokenSchema.Converter.Settings); 68 | } 69 | 70 | internal static class Converter 71 | { 72 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 73 | { 74 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 75 | DateParseHandling = DateParseHandling.None, 76 | Converters = 77 | { 78 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 79 | }, 80 | }; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/ExtensionInstallDeviceReport.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.InstalledAppDevices; 6 | // 7 | // var extensionInstallDeviceReport = ExtensionInstallDeviceReport.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.InstalledAppDevices 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class ExtensionInstallDeviceReport 19 | { 20 | [JsonProperty("devices", NullValueHandling = NullValueHandling.Ignore)] 21 | public List Devices { get; set; } 22 | 23 | [JsonProperty("nextPageToken", NullValueHandling = NullValueHandling.Ignore)] 24 | public string NextPageToken { get; set; } 25 | 26 | [JsonProperty("totalSize", NullValueHandling = NullValueHandling.Ignore)] 27 | public long? TotalSize { get; set; } 28 | } 29 | 30 | public partial class Device 31 | { 32 | [JsonProperty("deviceId", NullValueHandling = NullValueHandling.Ignore)] 33 | public string DeviceId { get; set; } 34 | 35 | [JsonProperty("machine", NullValueHandling = NullValueHandling.Ignore)] 36 | public string Machine { get; set; } 37 | } 38 | 39 | public partial class ExtensionInstallDeviceReport 40 | { 41 | public static ExtensionInstallDeviceReport FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.InstalledAppDevices.Converter.Settings); 42 | } 43 | 44 | public static class Serialize 45 | { 46 | public static string ToJson(this ExtensionInstallDeviceReport self) => JsonConvert.SerializeObject(self, cbcmSchema.InstalledAppDevices.Converter.Settings); 47 | } 48 | 49 | internal static class Converter 50 | { 51 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 52 | { 53 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 54 | DateParseHandling = DateParseHandling.None, 55 | Converters = 56 | { 57 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 58 | }, 59 | }; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/ExtensionInstallReport.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.InstalledAppsReport; 6 | // 7 | // var extensionInstallReport = ExtensionInstallReport.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.InstalledAppsReport 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using cbcmSchema.InstalledAppDevices; 16 | using Newtonsoft.Json; 17 | using Newtonsoft.Json.Converters; 18 | 19 | public partial class ExtensionInstallReport 20 | { 21 | [JsonProperty("installedApps", NullValueHandling = NullValueHandling.Ignore)] 22 | public List InstalledApps { get; set; } 23 | 24 | [JsonProperty("nextPageToken", NullValueHandling = NullValueHandling.Ignore)] 25 | public string NextPageToken { get; set; } 26 | 27 | [JsonProperty("totalSize", NullValueHandling = NullValueHandling.Ignore)] 28 | public long? TotalSize { get; set; } 29 | } 30 | 31 | public partial class InstalledApp : IFormattable 32 | { 33 | [JsonProperty("appId", NullValueHandling = NullValueHandling.Ignore)] 34 | public string AppId { get; set; } 35 | 36 | [JsonProperty("appType", NullValueHandling = NullValueHandling.Ignore)] 37 | public string AppType { get; set; } 38 | 39 | [JsonProperty("browserDeviceCount", NullValueHandling = NullValueHandling.Ignore)] 40 | [JsonConverter(typeof(ParseStringConverter))] 41 | public long? BrowserDeviceCount { get; set; } 42 | 43 | [JsonProperty("appInstallType", NullValueHandling = NullValueHandling.Ignore)] 44 | public string AppInstallType { get; set; } 45 | 46 | [JsonProperty("appSource", NullValueHandling = NullValueHandling.Ignore)] 47 | public string AppSource { get; set; } 48 | 49 | [JsonProperty("displayName", NullValueHandling = NullValueHandling.Ignore)] 50 | public string DisplayName { get; set; } 51 | 52 | [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] 53 | public string Description { get; set; } 54 | 55 | [JsonProperty("homepageUri", NullValueHandling = NullValueHandling.Ignore)] 56 | public Uri HomepageUri { get; set; } 57 | 58 | [JsonProperty("permissions", NullValueHandling = NullValueHandling.Ignore)] 59 | public List Permissions { get; set; } 60 | 61 | [JsonProperty("devices", NullValueHandling = NullValueHandling.Ignore)] 62 | public List Devices { get; set; } 63 | 64 | [JsonProperty("version", NullValueHandling = NullValueHandling.Ignore)] 65 | public string Version { get; set; } 66 | 67 | [JsonProperty("crxcavatorRiskScore", NullValueHandling = NullValueHandling.Ignore)] 68 | public string CrxcavatorRiskScore { get; set; } 69 | 70 | [JsonProperty("crxcavatorRiskUrl", NullValueHandling = NullValueHandling.Ignore)] 71 | public Uri CrxcavatorRiskUrl { get; set; } 72 | 73 | [JsonProperty("spinRiskScore", NullValueHandling = NullValueHandling.Ignore)] 74 | public string SpinRiskScore { get; set; } 75 | 76 | [JsonProperty("spinRiskUrl", NullValueHandling = NullValueHandling.Ignore)] 77 | public Uri SpinRiskUrl { get; set; } 78 | 79 | 80 | public override string ToString() 81 | { 82 | return this.ToString("S", CultureInfo.CurrentCulture); 83 | } 84 | 85 | public string ToString(string format, IFormatProvider formatProvider) 86 | { 87 | if (String.IsNullOrEmpty(format)) format = "S"; 88 | if (formatProvider == null) formatProvider = CultureInfo.CurrentCulture; 89 | 90 | switch (format.ToUpperInvariant()) 91 | { 92 | case "L": 93 | //"appId,displayName,version,crxcavatorRiskScore,crxcavatorRiskUrl,spinRiskScore,spinRiskUrl,browserDeviceCount,appInstallType" 94 | return String.Format("{0},\"{1}\",{2},{3},{4},{5},{6},{7},{8}", 95 | this.AppId, 96 | this.DisplayName, 97 | this.Version, 98 | this.CrxcavatorRiskScore, 99 | this.CrxcavatorRiskUrl != null ? this.CrxcavatorRiskUrl.ToString() : String.Empty, 100 | this.SpinRiskScore, 101 | this.SpinRiskUrl != null ? this.SpinRiskUrl.ToString() : String.Empty, 102 | this.BrowserDeviceCount.HasValue ? this.BrowserDeviceCount.Value.ToString() : String.Empty, 103 | this.AppInstallType); 104 | case "S": 105 | default: 106 | return String.Format("{0},{1},crx:{2},spinai:{3}", 107 | this.AppId, 108 | this.Version, 109 | this.CrxcavatorRiskScore, 110 | this.SpinRiskScore); 111 | 112 | } 113 | } 114 | } 115 | 116 | public partial class Device 117 | { 118 | [JsonProperty("deviceId", NullValueHandling = NullValueHandling.Ignore)] 119 | public string DeviceId { get; set; } 120 | 121 | [JsonProperty("machine", NullValueHandling = NullValueHandling.Ignore)] 122 | public string Machine { get; set; } 123 | 124 | public override string ToString() 125 | { 126 | return this.Machine; 127 | } 128 | } 129 | 130 | public partial class ExtensionInstallReport 131 | { 132 | public static ExtensionInstallReport FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.InstalledAppsReport.Converter.Settings); 133 | } 134 | 135 | public static class Serialize 136 | { 137 | public static string ToJson(this ExtensionInstallReport self) => JsonConvert.SerializeObject(self, cbcmSchema.InstalledAppsReport.Converter.Settings); 138 | } 139 | 140 | internal static class Converter 141 | { 142 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 143 | { 144 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 145 | DateParseHandling = DateParseHandling.None, 146 | Converters = 147 | { 148 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 149 | }, 150 | }; 151 | } 152 | 153 | 154 | 155 | internal class ParseStringConverter : JsonConverter 156 | { 157 | public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?); 158 | 159 | public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) 160 | { 161 | if (reader.TokenType == JsonToken.Null) return null; 162 | var value = serializer.Deserialize(reader); 163 | long l; 164 | if (Int64.TryParse(value, out l)) 165 | { 166 | return l; 167 | } 168 | throw new Exception("Cannot unmarshal type long"); 169 | } 170 | 171 | public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) 172 | { 173 | if (untypedValue == null) 174 | { 175 | serializer.Serialize(writer, null); 176 | return; 177 | } 178 | var value = (long)untypedValue; 179 | serializer.Serialize(writer, value.ToString()); 180 | return; 181 | } 182 | 183 | public static readonly ParseStringConverter Singleton = new ParseStringConverter(); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/ExtensionMgmtPolicy.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.ExtensionPolicy; 6 | // 7 | // var extensionMgmtPolicy = ExtensionMgmtPolicy.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.ExtensionPolicy 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class ExtensionMgmtPolicy 19 | { 20 | [JsonProperty("requests", NullValueHandling = NullValueHandling.Ignore)] 21 | public List Requests { get; set; } 22 | } 23 | 24 | public partial class Request 25 | { 26 | [JsonProperty("policyTargetKey", NullValueHandling = NullValueHandling.Ignore)] 27 | public PolicyTargetKey PolicyTargetKey { get; set; } 28 | 29 | [JsonProperty("policyValue", NullValueHandling = NullValueHandling.Ignore)] 30 | public PolicyValue PolicyValue { get; set; } 31 | 32 | [JsonProperty("updateMask", NullValueHandling = NullValueHandling.Ignore)] 33 | public UpdateMask UpdateMask { get; set; } 34 | } 35 | 36 | public partial class PolicyTargetKey 37 | { 38 | [JsonProperty("targetResource", NullValueHandling = NullValueHandling.Ignore)] 39 | public string TargetResource { get; set; } 40 | 41 | [JsonProperty("additionalTargetKeys", NullValueHandling = NullValueHandling.Ignore)] 42 | public AdditionalTargetKeys AdditionalTargetKeys { get; set; } 43 | } 44 | 45 | public partial class AdditionalTargetKeys 46 | { 47 | [JsonProperty("app_id", NullValueHandling = NullValueHandling.Ignore)] 48 | public string AppId { get; set; } 49 | } 50 | 51 | public partial class PolicyValue 52 | { 53 | [JsonProperty("policySchema", NullValueHandling = NullValueHandling.Ignore)] 54 | public string PolicySchema { get; set; } 55 | 56 | [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] 57 | public Value Value { get; set; } 58 | } 59 | 60 | public partial class Value 61 | { 62 | /// 63 | /// Valid aoo install type: {"ALLOWED", "FORCED", "BLOCKED"} 64 | /// 65 | [JsonProperty("appInstallType", NullValueHandling = NullValueHandling.Ignore)] 66 | public string AppInstallType { get; set; } 67 | } 68 | 69 | public partial class UpdateMask 70 | { 71 | [JsonProperty("paths", NullValueHandling = NullValueHandling.Ignore)] 72 | public string Paths { get; set; } 73 | } 74 | 75 | public partial class ExtensionMgmtPolicy 76 | { 77 | public static ExtensionMgmtPolicy FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.ExtensionPolicy.Converter.Settings); 78 | } 79 | 80 | public static class Serialize 81 | { 82 | public static string ToJson(this ExtensionMgmtPolicy self) => JsonConvert.SerializeObject(self, cbcmSchema.ExtensionPolicy.Converter.Settings); 83 | } 84 | 85 | internal static class Converter 86 | { 87 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 88 | { 89 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 90 | DateParseHandling = DateParseHandling.None, 91 | Converters = 92 | { 93 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 94 | }, 95 | }; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/MoveChromeBrowsersToOu.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.BrowserToOU; 6 | // 7 | // var moveChromeBrowsersToOu = MoveChromeBrowsersToOu.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.BrowserToOU 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class MoveChromeBrowsersToOu 19 | { 20 | [JsonProperty("org_unit_path", NullValueHandling = NullValueHandling.Ignore)] 21 | public string OrgUnitPath { get; set; } 22 | 23 | [JsonProperty("resource_ids", NullValueHandling = NullValueHandling.Ignore)] 24 | public string[] ResourceIds { get; set; } 25 | } 26 | 27 | public partial class MoveChromeBrowsersToOu 28 | { 29 | public static MoveChromeBrowsersToOu FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.BrowserToOU.Converter.Settings); 30 | } 31 | 32 | public static class Serialize 33 | { 34 | public static string ToJson(this MoveChromeBrowsersToOu self) => JsonConvert.SerializeObject(self, cbcmSchema.BrowserToOU.Converter.Settings); 35 | } 36 | 37 | internal static class Converter 38 | { 39 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 40 | { 41 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 42 | DateParseHandling = DateParseHandling.None, 43 | Converters = 44 | { 45 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 46 | }, 47 | }; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/OrgUnits.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.OU; 6 | // 7 | // var orgUnits = OrgUnits.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.OU 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class OrgUnits 19 | { 20 | [JsonProperty("organizationUnits", NullValueHandling = NullValueHandling.Ignore)] 21 | public List OrganizationUnits { get; set; } 22 | } 23 | 24 | public partial class OrganizationUnit 25 | { 26 | [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] 27 | public string Name { get; set; } 28 | 29 | [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] 30 | public string Description { get; set; } 31 | 32 | [JsonProperty("orgUnitPath", NullValueHandling = NullValueHandling.Ignore)] 33 | public string OrgUnitPath { get; set; } 34 | 35 | private string _orgUnitId = String.Empty; 36 | 37 | [JsonProperty("orgUnitId", NullValueHandling = NullValueHandling.Ignore)] 38 | public string OrgUnitId 39 | { 40 | get 41 | { 42 | return this.StripToken(this._orgUnitId, "id:"); 43 | } 44 | set 45 | { 46 | this._orgUnitId = value; 47 | } 48 | } 49 | 50 | [JsonProperty("parentOrgUnitPath", NullValueHandling = NullValueHandling.Ignore)] 51 | public string ParentOrgUnitPath { get; set; } 52 | 53 | private string _parentOrgUnitId = String.Empty; 54 | [JsonProperty("parentOrgUnitId", NullValueHandling = NullValueHandling.Ignore)] 55 | public string ParentOrgUnitId 56 | { 57 | get 58 | { 59 | return this.StripToken(this._parentOrgUnitId, "id:"); 60 | } 61 | set 62 | { 63 | this._parentOrgUnitId = value; 64 | } 65 | } 66 | 67 | [JsonProperty("blockInheritance", NullValueHandling = NullValueHandling.Ignore)] 68 | public bool? BlockInheritance { get; set; } 69 | 70 | private string StripToken(string originalText, string token) 71 | { 72 | if (String.IsNullOrEmpty(originalText)) 73 | return String.Empty; 74 | 75 | string[] stringSeparators = new string[] { token }; 76 | 77 | string[] result = originalText.Split(stringSeparators, StringSplitOptions.None); 78 | 79 | if (result.Length > 1) 80 | return result[1]; 81 | 82 | return originalText; 83 | } 84 | } 85 | 86 | public partial class OrgUnits 87 | { 88 | public static OrgUnits FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.OU.Converter.Settings); 89 | } 90 | 91 | public static class Serialize 92 | { 93 | public static string ToJson(this OrgUnits self) => JsonConvert.SerializeObject(self, cbcmSchema.OU.Converter.Settings); 94 | } 95 | 96 | internal static class Converter 97 | { 98 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 99 | { 100 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 101 | DateParseHandling = DateParseHandling.None, 102 | Converters = 103 | { 104 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 105 | }, 106 | }; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("cbcmSchema")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Google")] 12 | [assembly: AssemblyProduct("cbcmSchema")] 13 | [assembly: AssemblyCopyright("Copyright © Google 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("eaf5e83e-cbe9-4401-a644-aeeb2df990f9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/ResponseException.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.ApplicationException; 6 | // 7 | // var responseException = ResponseException.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.ApplicationException 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class ResponseException 19 | { 20 | [JsonProperty("error", NullValueHandling = NullValueHandling.Ignore)] 21 | public ResponseExceptionError Error { get; set; } 22 | } 23 | 24 | public partial class ResponseExceptionError 25 | { 26 | [JsonProperty("code", NullValueHandling = NullValueHandling.Ignore)] 27 | public long? Code { get; set; } 28 | 29 | [JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)] 30 | public string Message { get; set; } 31 | 32 | [JsonProperty("errors", NullValueHandling = NullValueHandling.Ignore)] 33 | public List Errors { get; set; } 34 | } 35 | 36 | public partial class ErrorElement 37 | { 38 | [JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)] 39 | public string Message { get; set; } 40 | 41 | [JsonProperty("domain", NullValueHandling = NullValueHandling.Ignore)] 42 | public string Domain { get; set; } 43 | 44 | [JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)] 45 | public string Reason { get; set; } 46 | } 47 | 48 | public partial class ResponseException 49 | { 50 | public static ResponseException FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.ApplicationException.Converter.Settings); 51 | } 52 | 53 | public static class Serialize 54 | { 55 | public static string ToJson(this ResponseException self) => JsonConvert.SerializeObject(self, cbcmSchema.ApplicationException.Converter.Settings); 56 | } 57 | 58 | internal static class Converter 59 | { 60 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 61 | { 62 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 63 | DateParseHandling = DateParseHandling.None, 64 | Converters = 65 | { 66 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 67 | }, 68 | }; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/SpinRiskItem.cs: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: 4 | // 5 | // using cbcmSchema.Spin; 6 | // 7 | // var spinRiskItem = SpinRiskItem.FromJson(jsonString); 8 | 9 | namespace cbcmSchema.Spin 10 | { 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | using System.Globalization; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Converters; 17 | 18 | public partial class SpinRiskItem 19 | { 20 | [JsonProperty("details", NullValueHandling = NullValueHandling.Ignore)] 21 | public Uri Details { get; set; } 22 | 23 | [JsonProperty("trustRate", NullValueHandling = NullValueHandling.Ignore)] 24 | public long? TrustRate { get; set; } 25 | 26 | [JsonProperty("appVersion", NullValueHandling = NullValueHandling.Ignore)] 27 | public string AppVersion { get; set; } 28 | 29 | public override string ToString() 30 | { 31 | return String.Format("spinai:{0}", this.TrustRate.HasValue ? this.TrustRate.Value.ToString() : String.Empty); 32 | } 33 | } 34 | 35 | public partial class SpinRiskItem 36 | { 37 | public static SpinRiskItem FromJson(string json) => JsonConvert.DeserializeObject(json, cbcmSchema.Spin.Converter.Settings); 38 | } 39 | 40 | public static class Serialize 41 | { 42 | public static string ToJson(this SpinRiskItem self) => JsonConvert.SerializeObject(self, cbcmSchema.Spin.Converter.Settings); 43 | } 44 | 45 | internal static class Converter 46 | { 47 | public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings 48 | { 49 | MetadataPropertyHandling = MetadataPropertyHandling.Ignore, 50 | DateParseHandling = DateParseHandling.None, 51 | Converters = 52 | { 53 | new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } 54 | }, 55 | }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/cbcmSchema.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EAF5E83E-CBE9-4401-A644-AEEB2DF990F9} 8 | Library 9 | Properties 10 | cbcmschema 11 | cbcmschema 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] 5 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/obj/Debug/cbcmSchema.csproj.AssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/cbcmschema/obj/Debug/cbcmSchema.csproj.AssemblyReference.cache -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/obj/Release/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] 5 | -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/obj/Release/cbcmSchema.csproj.AssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Deprecated/dotnet/cbcm-csharp/cbcmschema/obj/Release/cbcmSchema.csproj.AssemblyReference.cache -------------------------------------------------------------------------------- /Deprecated/dotnet/cbcm-csharp/cbcmschema/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Python/BlockExtensionBasedOnRiskScoreOutput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Python/BlockExtensionBasedOnRiskScoreOutput.png -------------------------------------------------------------------------------- /Python/README.md: -------------------------------------------------------------------------------- 1 | ## Get extension list using Takeout API 2 | Using the [script](extension_query.py) ( 3 | [python 2.7 compatible version](extension_query_py2.py)) to download extensions 4 | list from all browsers. 5 | 6 | ### Setup Access to API 7 | 8 | Before using CBCM Takeout API you will need to do some initial setup: 9 | 10 | 1. Enable the Admin SDK API (if not already enabled) in the Google Developer 11 | Console by following this 12 | [link](https://console.developers.google.com/apis/api/admin.googleapis.com/overview?project=_) 13 | and selecting the project on which you wish to enable the API. 14 | 1. Create a service account and have the necessary service account keys for 15 | this service account. You can follow 16 | [this](https://developers.google.com/admin-sdk/directory/v1/guides/delegation) 17 | for creating a service account and getting the service account keys. You 18 | must grant the service account the "Service Account User" role on the 19 | permissions during creation. 20 | 1. The client ID for this service account will need to be authorized for the 21 | OAuth scopes listed below in the Admin Console under Security -> Advanced 22 | settings -> Manage API client access. On this page, the Client ID 23 | corresponds to the Unique ID of your service account. You will need to 24 | authorize the client ID for the scope: 25 | * https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly 26 | 27 | ### Running the Script 28 | 29 | 30 | With the service account keys, you can now run the script which uses Google API 31 | Client Libraries to make the necessary queries to the API. The script requires 32 | that both the service account keys you downloaded from the developers console as 33 | well as the e-mail of an admin user in your domain that is allowed to access the 34 | data you wish to query. 35 | 36 | You can run the script from the command-line: 37 | ``` 38 | python extension_query.py --service_account_key_path --admin_email 39 | ``` 40 | (also: `python extension_query.py --help` for a reminder of the 41 | argument names) 42 | 43 | ## Example Data output 44 | 45 | Here is an example of what that data will look like: 46 |  47 | 48 | ## Move Chrome browsers between Organization Units 49 | You can use the [moveBrowserToOrgUnit](moveBrowserToOrgUnit.py) to move enrolled browser between Organization Units (OU). 50 | 51 | Note: You will need to add the customer ID, the service account key JSON file, and the destination OU path to the script. 52 | 53 | 👉 Add the customer id [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/moveBrowserToOrgUnit.py#L12). You can find the customer Id by navigating to the Google Admin Console > Account > Account Settings. 54 | 55 | 👉 Add the path to the OAuth client secret file [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/moveBrowserToOrgUnit.py#L10). You can download the file from the Google Developer Console 56 | 57 | 👉 Add the [destination OU path](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/moveBrowserToOrgUnit.py#L14). An example of the destination OU path 'North America/Austin/AUS Managed User' 58 | 59 | ``` 60 | python moveBrowserToOrgUnit.py 61 | ``` 62 | 63 | ## Get Chrome Signed-On User account names 64 | You can use the [cbcm-profiles-export.py](cbcm-profiles-export.py) to get a CSV export of Signed-On User account names. 65 | 66 | Note: You will need to add the customer ID, the service account key JSON file, and the destination OU path to the script. 67 | 68 | 👉 Add the customer id [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/cbcm-profiles-export.py#L24). You can find the customer Id by navigating to the Google Admin Console > Account > Account Settings. 69 | 70 | 👉 Add the path to the OAuth client secret file [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/cbcm-profiles-export.py#L22). You can download the file from the Google Developer Console 71 | 72 | 👉 Optional: Add the [destination OU path](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/cbcm-profiles-export.py#L26). An example of the destination OU path 'North America/Austin/AUS Managed User' 73 | 74 | ``` 75 | python cbcm-profiles-export.py 76 | ``` 77 | 78 | ## Get extension list with Chrome Profile 79 | You can use the [cbcm-browser-extension-profile-export.py](cbcm-browser-extension-profile-export.py) to get a CSV export of all extensions from managed browser including Profile and Signed-On User account names. 80 | 81 | Note: You will need to add the customer ID, the service account key JSON file, and the destination OU path to the script. 82 | 83 | 👉 Add the customer id [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/cbcm-profiles-export.py#L24). You can find the customer Id by navigating to the Google Admin Console > Account > Account Settings. 84 | 85 | 👉 Add the path to the OAuth client secret file [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/cbcm-profiles-export.py#L22). You can download the file from the Google Developer Console 86 | 87 | 👉 Optional: Add the [destination OU path](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/cbcm-profiles-export.py#L26). An example of the destination OU path 'North America/Austin/AUS Managed User' 88 | 89 | ``` 90 | python cbcm-browser-extension-profile-export.py 91 | ``` 92 | Here is an example of what that data will look like: 93 |  94 | 95 | 96 | ## BlockExtensionBasedOnRiskScore Script 97 | 98 | This Python script, `BlockExtensionBasedOnRiskScore.py`, automates the process of identifying and blocking potentially risky Chrome extensions in a Chrome Browser Cloud Management environment. It evaluates extensions based on risk scores obtained from Crxcavator and Spin.ai. 99 | 100 | Note: If the risk scores of the newest versions of installed extensions are not available, this script will pick up the scores from the older versions. 101 | 102 | ### Configuration 103 | 104 | 👉 `SERVICE_ACCOUNT_FILE`: Path to your service account key JSON file. 105 | 106 | 👉 `CUSTOMER_ID`: Your Google Workspace customer ID. You can find the customer Id by navigating to the Google Admin Console > Account > Account Settings. 107 | 108 | 👉 `CRX_RISK_THRESHOLD` and `SPIN_RISK_THRESHOLD`: The risk thresholds for Crxcavator and Spin.ai scores. 109 | 110 | 👉 `ADMIN_USER_EMAIL`: The email address of an admin user in your Google Workspace. 111 | 112 | 👉 `TARGET_OU`: The OU name where extensions will be blocked. An example of the destination OU name would be ’AUS Managed User' 113 | 114 | 115 | ``` 116 | python BlockExtensionBasedOnRiskScore.py 117 | ``` 118 | 119 |  120 | 121 | ## Get information about Chrome browsers that are managed by your organization using Chrome Enterprise Core 122 | [cbcm-browser-basic-export.py](https://github.com/google/ChromeBrowserEnterprise/blob/main/Python/cbcm-browser-basic-export.py) automates the process of collecting and organizing important details about Chrome browsers managed using Chrome Enterprise Core (CEC), making it easier to keep track of them. 123 | 124 | The output include things like: 125 | * Which computer it's on 126 | * The browser's version 127 | * Whether it has any updates waiting 128 | * Number of installed extensions 129 | * Number of configured browser policies 130 | * When it was last used 131 | 132 | The code takes all the collected browser information and neatly puts it into a CSV file. 133 | -------------------------------------------------------------------------------- /Python/cbcm-browser-basic-export.py: -------------------------------------------------------------------------------- 1 | # cbcm-browser-basic-export 2 | 3 | #Libraries and Dependencies 4 | #pip install google-api-python-client 5 | #pip install google-auth 6 | #pip install google-auth-oauthlib 7 | #pip install google-auth-httplib2 8 | #pip install urllib3 9 | 10 | import csv 11 | import json 12 | 13 | from google.oauth2 import service_account 14 | 15 | from google.auth.transport.requests import AuthorizedSession 16 | from google.oauth2.service_account import Credentials 17 | from urllib.parse import urlparse, parse_qs, parse_qsl, urlencode 18 | from string import Template 19 | 20 | #/******* BEGIN: Customer to modify this section *******/ 21 | #Add service account key json file. 22 | SERVICE_ACCOUNT_KEY_PATH = '' 23 | #Add the customer id here. You can find the customer Id by navigating to the Google Admin Console > Account > Account Settings. 24 | CUSTOMER_ID = "" 25 | #Add OU path. An example of the destination OU path 'North America/Austin/AUS Managed User' 26 | ORG_UNIT_PATH = "" 27 | # CSV Filename 28 | CSV_FILENAME = "cbcm-browser-basic-export.csv" 29 | #/******* END: Customer to modify this section *******/ 30 | 31 | 32 | #/***** Get authorization token *****/ 33 | def create_authToken(): 34 | service_account_info = json.load(open(SERVICE_ACCOUNT_KEY_PATH)) 35 | 36 | credentials = Credentials.from_service_account_info( 37 | service_account_info, 38 | scopes=[ 39 | 'https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly']) 40 | 41 | return AuthorizedSession(credentials) 42 | 43 | #/***** Modify the query string. *****/ 44 | def patch_url(url, **kwargs): 45 | return urlparse(url)._replace(query=urlencode( 46 | dict(parse_qsl(urlparse(url).query), **kwargs))).geturl() 47 | 48 | #/***** Compute list of managed browsers. *****/ 49 | #/***** Args: *****/ 50 | #/***** data: the data fetched from the Takeout API. *****/ 51 | def computeBrowserList(enrolledBrowserList, data): 52 | try: 53 | for device in data['browsers']: 54 | if 'browsers' not in device: 55 | continue 56 | for browser in device['browsers']: 57 | currrent_profile = { 58 | 'deviceId':device['deviceId'], 59 | 'orgUnitPath':device['orgUnitPath'], 60 | 'machineName':device['machineName'], 61 | 'browserVersion':browser['browserVersion'], 62 | 'channel':browser['channel'], 63 | 'pendingInstallVersion': (browser['pendingInstallVersion'] if 'pendingInstallVersion' in browser else ''), 64 | 'extensionCount':device['extensionCount'], 65 | 'policyCount':device['policyCount'], 66 | 'lastActivityTime':device['lastActivityTime'], 67 | 'lastDeviceUser':device['lastDeviceUser'] 68 | } 69 | 70 | enrolledBrowserList.append(currrent_profile) 71 | 72 | except Exception as e: 73 | print(e) 74 | 75 | #/***** Get enrolled browser data from CBCM for given OU path. *****/ 76 | def get_enrolledBrowsers(): 77 | next_page_token = '' 78 | chromeBrowserServiceUrl = "https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers?projection=FULL&maxResults=100&orgUnitPath={1}&&pageToken=".format(CUSTOMER_ID, 79 | ORG_UNIT_PATH) 80 | browsers_processed = 0 81 | enrolledBrowserList = list() 82 | authSession = create_authToken() 83 | while True: 84 | response = authSession.request( 85 | "GET", 86 | chromeBrowserServiceUrl 87 | ) 88 | data = json.loads(response._content.decode("utf-8")) 89 | browsers_in_data = len(data['browsers']) 90 | browsers_processed += browsers_in_data 91 | 92 | computeBrowserList(enrolledBrowserList, data) 93 | 94 | if data.get("nextPageToken") is not None: 95 | next_page_token = data.get("nextPageToken") 96 | chromeBrowserServiceUrl = patch_url(chromeBrowserServiceUrl, pageToken=next_page_token) 97 | else: 98 | next_page_token = '' 99 | 100 | if len(next_page_token) == 0: 101 | break; 102 | return enrolledBrowserList 103 | 104 | #/***** Get enrolled browser data from CBCM for given OU path. *****/ 105 | def EnrolledBrowserExportAsCSV(): 106 | try: 107 | browserProfileList = get_enrolledBrowsers() 108 | columnHeader = ['deviceId', 'orgUnitPath', 'machineName', 'browserVersion', 'channel', 'pendingInstallVersion', 'extensionCount', 'policyCount', 'lastActivityTime', 'lastDeviceUser'] 109 | 110 | with open (CSV_FILENAME, mode='w', encoding='utf-8', newline='') as csv_file: 111 | writer = csv.DictWriter(csv_file, fieldnames=columnHeader) 112 | writer.writeheader() 113 | writer.writerows(browserProfileList) 114 | 115 | 116 | except Exception as e: 117 | print(e) 118 | 119 | 120 | 121 | 122 | 123 | # get basic browser data 124 | EnrolledBrowserExportAsCSV() -------------------------------------------------------------------------------- /Python/cbcm-browser-extension-profile-export-Capture.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Python/cbcm-browser-extension-profile-export-Capture.PNG -------------------------------------------------------------------------------- /Python/cbcm-browser-extension-profile-export.py: -------------------------------------------------------------------------------- 1 | # cbcm-browser-extension-profile-export 2 | 3 | #Libraries and Dependencies 4 | #pip install google-api-python-client 5 | #pip install google-auth 6 | #pip install google-auth-oauthlib 7 | #pip install google-auth-httplib2 8 | #pip install urllib3 9 | 10 | import csv 11 | import json 12 | 13 | from google.oauth2 import service_account 14 | 15 | from google.auth.transport.requests import AuthorizedSession 16 | from google.oauth2.service_account import Credentials 17 | from urllib.parse import urlparse, parse_qs, parse_qsl, urlencode 18 | from string import Template 19 | 20 | #/******* BEGIN: Customer to modify this section *******/ 21 | #Add service account key json file. 22 | SERVICE_ACCOUNT_KEY_PATH = '' 23 | #Add the customer id here. You can find the customer Id by navigating to the Google Admin Console > Account > Account Settings. 24 | CUSTOMER_ID = "" 25 | #Add OU path. An example of the destination OU path 'North America/Austin/AUS Managed User' 26 | ORG_UNIT_PATH = "" 27 | # CSV Filename 28 | CSV_FILENAME = "cbcm-browser-extension-profile-export.csv" 29 | #/******* END: Customer to modify this section *******/ 30 | 31 | 32 | #/***** Get authorization token *****/ 33 | def create_authToken(): 34 | service_account_info = json.load(open(SERVICE_ACCOUNT_KEY_PATH)) 35 | 36 | credentials = Credentials.from_service_account_info( 37 | service_account_info, 38 | scopes=[ 39 | 'https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly']) 40 | 41 | return AuthorizedSession(credentials) 42 | 43 | #/***** Modify the query string. *****/ 44 | def patch_url(url, **kwargs): 45 | return urlparse(url)._replace(query=urlencode( 46 | dict(parse_qsl(urlparse(url).query), **kwargs))).geturl() 47 | 48 | #/***** Compute list of managed browser profiles. *****/ 49 | #/***** Args: *****/ 50 | #/***** extensions_list: the extension list dictionary to fill. *****/ 51 | #/***** data: the data fetched from the Takeout API. *****/ 52 | def computeBrowserProfileList(browserProfileList, data): 53 | try: 54 | for device in data['browsers']: 55 | if 'browsers' not in device: 56 | continue 57 | for browser in device['browsers']: 58 | if 'profiles' not in browser: 59 | continue 60 | for profile in browser['profiles']: 61 | chromeProfile = profile.get('chromeSignedInUserEmail','') 62 | 63 | if 'extensions' not in profile: 64 | continue 65 | for extension in profile['extensions']: 66 | extensionId = extension['extensionId'] 67 | extensionVersion = extension.get('version', ''), 68 | extensionName = extension.get('name', ''), 69 | extensionPermissions = extension.get('permissions', ''), 70 | extensionInstallType = extension.get('installType', '') 71 | 72 | currrent_profile = { 73 | 'machineName':device['machineName'], 74 | 'lastDeviceUser':device['lastDeviceUser'], 75 | 'profileName':profile['name'], 76 | 'chromeSignedInUserEmail':chromeProfile, 77 | 'extensionId':extensionId, 78 | 'extensionName':extensionName, 79 | 'extensionVersion':extensionVersion, 80 | 'extensionPermissions':extensionPermissions, 81 | 'extensionInstallType':extensionInstallType 82 | } 83 | 84 | browserProfileList.append(currrent_profile) 85 | 86 | except Exception as e: 87 | print(e) 88 | 89 | #/***** Get enrolled browser data from CBCM for given OU path. *****/ 90 | def get_enrolledBrowsers(): 91 | next_page_token = '' 92 | chromeBrowserServiceUrl = "https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers?projection=FULL&maxResults=100&orgUnitPath={1}&&pageToken=".format(CUSTOMER_ID, 93 | ORG_UNIT_PATH) 94 | browsers_processed = 0 95 | browserProfileList = list() 96 | authSession = create_authToken() 97 | while True: 98 | response = authSession.request( 99 | "GET", 100 | chromeBrowserServiceUrl 101 | ) 102 | data = json.loads(response._content.decode("utf-8")) 103 | browsers_in_data = len(data['browsers']) 104 | browsers_processed += browsers_in_data 105 | 106 | computeBrowserProfileList(browserProfileList, data) 107 | 108 | if data.get("nextPageToken") is not None: 109 | next_page_token = data.get("nextPageToken") 110 | chromeBrowserServiceUrl = patch_url(chromeBrowserServiceUrl, pageToken=next_page_token) 111 | else: 112 | next_page_token = '' 113 | 114 | if len(next_page_token) == 0: 115 | break; 116 | return browserProfileList 117 | 118 | #/***** Get enrolled browser data from CBCM for given OU path. *****/ 119 | def BrowserProfileAsCSV(): 120 | try: 121 | browserProfileList = get_enrolledBrowsers() 122 | columnHeader = ['machineName', 'lastDeviceUser', 'profileName', 'chromeSignedInUserEmail', 'extensionId', 'extensionName', 'extensionVersion', 'extensionPermissions', 'extensionInstallType'] 123 | 124 | with open (CSV_FILENAME, mode='w', encoding='utf-8', newline='') as csv_file: 125 | writer = csv.DictWriter(csv_file, fieldnames=columnHeader) 126 | writer.writeheader() 127 | writer.writerows(browserProfileList) 128 | 129 | 130 | except Exception as e: 131 | print(e) 132 | 133 | 134 | 135 | 136 | 137 | # get profile data 138 | BrowserProfileAsCSV() 139 | -------------------------------------------------------------------------------- /Python/cbcm-profiles-export.py: -------------------------------------------------------------------------------- 1 | # cbcm-profiles-export 2 | 3 | #Libraries and Dependencies 4 | #pip install google-api-python-client 5 | #pip install google-auth 6 | #pip install google-auth-oauthlib 7 | #pip install google-auth-httplib2 8 | #pip install urllib3 9 | 10 | import csv 11 | import json 12 | 13 | from google.oauth2 import service_account 14 | 15 | from google.auth.transport.requests import AuthorizedSession 16 | from google.oauth2.service_account import Credentials 17 | from urllib.parse import urlparse, parse_qs, parse_qsl, urlencode 18 | from string import Template 19 | 20 | #/******* BEGIN: Customer to modify this section *******/ 21 | #Add service account key json file. 22 | SERVICE_ACCOUNT_KEY_PATH = '' 23 | #Add the customer id here. You can find the customer Id by navigating to the Google Admin Console > Account > Account Settings. 24 | CUSTOMER_ID = "" 25 | #Add OU path. An example of the destination OU path 'North America/Austin/AUS Managed User' 26 | ORG_UNIT_PATH = "" 27 | # CSV Filename 28 | CSV_FILENAME = "chromebrowser-profiles.csv" 29 | #/******* END: Customer to modify this section *******/ 30 | 31 | 32 | #/***** Get authorization token *****/ 33 | def create_authToken(): 34 | service_account_info = json.load(open(SERVICE_ACCOUNT_KEY_PATH)) 35 | 36 | credentials = Credentials.from_service_account_info( 37 | service_account_info, 38 | scopes=[ 39 | 'https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly']) 40 | 41 | return AuthorizedSession(credentials) 42 | 43 | #/***** Modify the query string. *****/ 44 | def patch_url(url, **kwargs): 45 | return urlparse(url)._replace(query=urlencode( 46 | dict(parse_qsl(urlparse(url).query), **kwargs))).geturl() 47 | 48 | #/***** Compute list of managed browser profiles. *****/ 49 | #/***** Args: *****/ 50 | #/***** extensions_list: the extension list dictionary to fill. *****/ 51 | #/***** data: the data fetched from the Takeout API. *****/ 52 | def computeBrowserProfileList(browserProfileList, data): 53 | try: 54 | for device in data['browsers']: 55 | if 'browsers' not in device: 56 | continue 57 | for browser in device['browsers']: 58 | if 'profiles' not in browser: 59 | continue 60 | for profile in browser['profiles']: 61 | chromeProfile = profile.get('chromeSignedInUserEmail','') 62 | if chromeProfile == "": 63 | continue 64 | 65 | currrent_profile = { 66 | 'machineName':device['machineName'], 67 | 'profileName':profile['name'], 68 | 'chromeSignedInUserEmail':chromeProfile 69 | } 70 | 71 | browserProfileList.append(currrent_profile) 72 | 73 | except Exception as e: 74 | print(e) 75 | 76 | #/***** Get enrolled browser data from CBCM for given OU path. *****/ 77 | def get_enrolledBrowsers(): 78 | next_page_token = '' 79 | chromeBrowserServiceUrl = "https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers?projection=FULL&maxResults=100&orgUnitPath={1}&&pageToken=".format(CUSTOMER_ID, 80 | ORG_UNIT_PATH) 81 | browsers_processed = 0 82 | browserProfileList = list() 83 | authSession = create_authToken() 84 | while True: 85 | response = authSession.request( 86 | "GET", 87 | chromeBrowserServiceUrl 88 | ) 89 | data = json.loads(response._content.decode("utf-8")) 90 | browsers_in_data = len(data['browsers']) 91 | browsers_processed += browsers_in_data 92 | 93 | computeBrowserProfileList(browserProfileList, data) 94 | 95 | if data.get("nextPageToken") is not None: 96 | next_page_token = data.get("nextPageToken") 97 | chromeBrowserServiceUrl = patch_url(chromeBrowserServiceUrl, pageToken=next_page_token) 98 | else: 99 | next_page_token = '' 100 | 101 | if len(next_page_token) == 0: 102 | break; 103 | return browserProfileList 104 | 105 | #/***** Get enrolled browser data from CBCM for given OU path. *****/ 106 | def BrowserProfileAsCSV(): 107 | try: 108 | browserProfileList = get_enrolledBrowsers() 109 | columnHeader = ['machineName', 'profileName', 'chromeSignedInUserEmail'] 110 | 111 | with open (CSV_FILENAME, mode='w', encoding='utf-8', newline='') as csv_file: 112 | writer = csv.DictWriter(csv_file, fieldnames=columnHeader) 113 | writer.writeheader() 114 | writer.writerows(browserProfileList) 115 | 116 | 117 | except Exception as e: 118 | print(e) 119 | 120 | 121 | 122 | 123 | 124 | # get profile data 125 | BrowserProfileAsCSV() 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /Python/cloudidentitymembership.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import Optional, List 3 | 4 | 5 | @dataclass 6 | class MemberKey: 7 | id: Optional[str] = None 8 | 9 | 10 | @dataclass 11 | class PreferredMemberKey: 12 | id: Optional[str] = None 13 | device_id: Optional[str] = None 14 | name: Optional[str] = None 15 | is_member: Optional[bool] = False 16 | 17 | 18 | @dataclass 19 | class Role: 20 | name: Optional[str] = None 21 | 22 | 23 | @dataclass 24 | class Membership: 25 | name: Optional[str] = None 26 | member_key: Optional[MemberKey] = None 27 | role: Optional[Role] = None 28 | preferred_member_key: Optional[PreferredMemberKey] = None 29 | 30 | 31 | @dataclass 32 | class Cloudidentitymembership: 33 | memberships: Optional[List[Membership]] = None 34 | -------------------------------------------------------------------------------- /Python/connectors/splunk/README.md: -------------------------------------------------------------------------------- 1 | # Splunk Alert Action Quick Setup 2 | ### Option 1 (Splunk Cloud and Splunk Enterprise) 3 | 1. Zip (For Splunk Enterprise) or Tar(For Splunk Cloud and Enterprise) the `cbcm` folder. 4 | 2. Log in to Splunk Cloud/Enterprise and navigate to `Apps > Manage Apps`. 5 | 3. Click `Install app from file`. 6 | 4. For Splunk Enterprise click `Choose File` and select the zip/tar file that you want created in Step 1. For Splunk Cloud click the `Upload App` button and select the tar file that you created in Step 1. (You will have to sign in to your Splunk.com account) 7 | 5. Click on `Upload`. 8 | 9 | ### Option 2 (For Splunk Enterprise Only) 10 | 1. Open the `$SPLUNK_HOME/etc/apps/` directory 11 | 2. Copy the `cbcm` directory into it. 12 | 3. Restart the Splunk Enterprise instance. 13 | 14 | 15 | # Splunk Alert Action Detailed Setup For Splunk Enterprise 16 | 17 | > While following the below steps please create the directories if they do not exist. 18 | 19 | > Please review Splunk guidance [here](https://dev.splunk.com/enterprise/docs/devtools/customalertactions/configappcaa/) 20 | 21 | ## Manual Setup For Splunk Enterprise 22 | 1. Open the `$SPLUNK_HOME/etc/apps/appname/appserver/static/` directory and place an image for the app icon within the directory. This should be a png file with size 48x48 pixel. In our example the appname is `cbcm` hence the directory path will be `$SPLUNK_HOME/etc/apps/cbcm/`. We have named the file as [app_icon.png](./cbcm/appserver/static/app_icon.png) in our example. Any custom name can be used to name the png file. 23 | 24 | 2. Open the `$SPLUNK_HOME/etc/apps/cbcm/default/` directory and create a file called [alert_actions.conf](./cbcm/default/alert_actions.conf). 25 | 26 | > Please note we have mentioned the root as `[cbcm]` in our case. This root value has to correspond to the name of the python script and html files. 27 | 28 | 3. In the `$SPLUNK_HOME/etc/apps/cbcm/default/` directory create a file called [app.conf](./cbcm/default/app.conf). 29 | 30 | 4. Open the `$SPLUNK_HOME/etc/apps/cbcm/default/data/ui/alerts` directory and create a file called [cbcm.html](./cbcm/default/data/ui/alerts/cbcm.html). The filename of the html file corresponds to the root element of the `alert_actions.conf` file as stated above. 31 | 32 | > Please note that the names of the various input elements in the html file (for e.g. `action.cbcm.param.custid`) have to correspond to the values specified in the `savedsearches.conf`.spec file. 33 | 34 | 5. Open the `$SPLUNK_HOME/etc/apps/cbcm/bin` directory and create a file called [cbcm.py](./cbcm/bin/cbcm.py).The filename of the python file corresponds to the root element of the `alert_actions.conf` file. 35 | 36 | 6. Open the `$SPLUNK_HOME/etc/apps/cbcm/bin` directory and create a file called [import_declare_test.py](./cbcm/bin/import_declare_test.py). This file helps import your libraries in the `lib` directory. 37 | 38 | 7. Create the `$SPLUNK_HOME/etc/apps/cbcm/lib/` directory. Manually copy the python dependencies. The lib directory should look something like [this](./screenshot/lib.png) once all dependencies have been copied. 39 | 40 | 41 | 8. Open the `$SPLUNK_HOME/etc/apps/cbcm/README/` directory and create a file called [savedsearches.conf.spec](./cbcm/README/savedsearches.conf.spec). The line items correspond to the html input elements of `cbcm.html`. 42 | 43 | 9. Open the `$SPLUNK_HOME/etc/apps/cbcm/metadata/` directory and add the [default.meta](./cbcm/metadata/default.meta) file. 44 | 45 | 10. Restart the Splunk Enterprise instance. 46 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/README/alert_actions.conf.spec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Python/connectors/splunk/cbcm/README/alert_actions.conf.spec -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/README/savedsearches.conf.spec: -------------------------------------------------------------------------------- 1 | action.cbcm.param.oupath = 2 | action.cbcm.param.servicekey = 3 | action.cbcm.param.custid = 4 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/appserver/static/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Python/connectors/splunk/cbcm/appserver/static/app_icon.png -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/bin/README: -------------------------------------------------------------------------------- 1 | This is where you put any scripts you want to add to this app. 2 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/bin/cbcm.py: -------------------------------------------------------------------------------- 1 | import import_declare_test 2 | import os 3 | import logging 4 | import sys 5 | import requests 6 | import json 7 | import logging.handlers 8 | from google.auth.credentials import with_scopes_if_required 9 | from google.auth.transport.requests import AuthorizedSession 10 | from google.oauth2 import service_account 11 | 12 | def setup_logger(level): 13 | logger = logging.getLogger("cbcm_alert_logger") 14 | logger.propagate = False 15 | logger.setLevel(level) 16 | file_handler = logging.handlers.RotatingFileHandler(os.environ['SPLUNK_HOME'] + '/var/log/splunk/cbcm_alert.log',maxBytes=2500000,backupCount=5) 17 | formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') 18 | file_handler.setFormatter(formatter) 19 | logger.addHandler(file_handler) 20 | return logger 21 | 22 | logger = setup_logger(logging.INFO) 23 | 24 | # Move managed browser to restricted OU 25 | def move2ouMB(config, device_id): 26 | oupath = config.get('oupath') 27 | custid = config.get('custid') 28 | servicekey = json.loads(config.get('servicekey')) 29 | credentials = service_account.Credentials.from_service_account_info(servicekey) 30 | credentials = with_scopes_if_required(credentials,\ 31 | ["https://www.googleapis.com/auth/admin.directory.device.chromebrowsers"],) 32 | response = AuthorizedSession(credentials).request("POST", 33 | 'https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers/moveChromeBrowsersToOu'.format(custid),\ 34 | data=json.dumps({"org_unit_path": oupath,\ 35 | "resource_ids": [device_id]})) 36 | logger.info("response code: {0}".format(response.status_code)) 37 | logger.info("response: {0}".format(response._content.decode("utf-8"))) 38 | 39 | # Move user to restricted OU for a managed Chrome OS device 40 | def move2ouMD(config, device_user, profile_user): 41 | oupath = config.get('oupath') 42 | custid = config.get('custid') 43 | servicekey = json.loads(config.get('servicekey')) 44 | credentials = service_account.Credentials.from_service_account_info(servicekey) 45 | credentials = with_scopes_if_required(credentials,\ 46 | ["https://www.googleapis.com/auth/admin.directory.user"],) 47 | if device_user != "": 48 | logger.info("Moving Chrome device user to Quarantine OU") 49 | response = AuthorizedSession(credentials).request("PUT", 50 | 'https://admin.googleapis.com/admin/directory/v1/users/{0}'.format(device_user),\ 51 | data=json.dumps({"orgUnitPath": oupath})) 52 | if profile_user != "" and device_user != profile_user: 53 | logger.info("Moving Chrome profile user to Quarantine OU") 54 | response = AuthorizedSession(credentials).request("PUT", 55 | 'https://admin.googleapis.com/admin/directory/v1/users/{0}'.format(profile_user),\ 56 | data=json.dumps({"orgUnitPath": oupath})) 57 | logger.info("response code: {0}".format(response.status_code)) 58 | logger.info("response: {0}".format(response._content.decode("utf-8"))) 59 | 60 | # Move user to restricted OU for a managed profile 61 | def move2ouMP(config, profile_user): 62 | oupath = config.get('oupath') 63 | custid = config.get('custid') 64 | servicekey = json.loads(config.get('servicekey')) 65 | credentials = service_account.Credentials.from_service_account_info(servicekey) 66 | credentials = with_scopes_if_required(credentials,\ 67 | ["https://www.googleapis.com/auth/admin.directory.user"],) 68 | response = AuthorizedSession(credentials).request("PUT", 69 | 'https://admin.googleapis.com/admin/directory/v1/users/{0}'.format(profile_user),\ 70 | data=json.dumps({"orgUnitPath": oupath})) 71 | logger.info("response code: {0}".format(response.status_code)) 72 | logger.info("response: {0}".format(response._content.decode("utf-8"))) 73 | 74 | 75 | def main(): 76 | if len(sys.argv) > 1 and sys.argv[1] == "--execute": 77 | payload = json.loads(sys.stdin.read()) 78 | logger.info(payload.get('result')) 79 | config = payload.get('configuration') 80 | event = payload.get('result') 81 | if event.get('client_type') == 'CHROME_BROWSER': 82 | logger.info("Moving Chrome Browser to Quarantine OU") 83 | move2ouMB(config, event.get('directory_device_id')) 84 | elif event.get('client_type') == 'CHROME_OS_DEVICE': 85 | move2ouMD(config, event.get('device_user'), event.get('profile_user')) 86 | elif event.get('client_type') == 'CHROME_BROWSER_PROFILE': 87 | logger.info("Moving Chrome Profile to Quarantine OU") 88 | move2ouMP(config, event.get('profile_user')) 89 | else: 90 | logger.info("Unknown Client Type") 91 | 92 | 93 | if __name__ == "__main__": 94 | main() 95 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/bin/import_declare_test.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import sys 4 | import re 5 | from os.path import dirname 6 | 7 | ta_name = 'cbcm' 8 | pattern = re.compile(r'[\\/]etc[\\/]apps[\\/][^\\/]+[\\/]bin[\\/]?$') 9 | new_paths = [path for path in sys.path if not pattern.search(path) or ta_name in path] 10 | new_paths.append(os.path.join(dirname(dirname(__file__)), "lib")) 11 | new_paths.insert(0, os.path.sep.join([os.path.dirname(__file__), ta_name])) 12 | sys.path = new_paths 13 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/default/alert_actions.conf: -------------------------------------------------------------------------------- 1 | [cbcm] 2 | is_custom = 1 3 | label = CBCM Remediation 4 | description = Move browser to restricted OU 5 | icon_path = app_icon.png 6 | payload_format = json 7 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/default/app.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Splunk app configuration file 3 | # 4 | 5 | [install] 6 | is_configured = 1 7 | state = enabled 8 | install_source_checksum = 6e4adf0278ab1212ff82423d4accb7c22ae5ed08 9 | 10 | [ui] 11 | is_visible = 0 12 | label = cbcm 13 | 14 | [launcher] 15 | author = cbcm 16 | description = This is a custom alert action for cbcm i.e. moving OU 17 | version = 1.0.0 18 | 19 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/default/data/ui/alerts/cbcm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Destination OU Path 4 | 5 | 6 | 7 | 8 | The path of the destination OU. 9 | 10 | 11 | 12 | 13 | Customer ID 14 | 15 | 16 | 17 | 18 | The Customer Id. 19 | 20 | 21 | 22 | 23 | Service Key JSON 24 | 25 | 26 | 27 | 28 | The service account key in JSON format. 29 | Learn More 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/default/data/ui/nav/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/default/data/ui/views/README: -------------------------------------------------------------------------------- 1 | Add all the views that your app needs in this directory 2 | -------------------------------------------------------------------------------- /Python/connectors/splunk/cbcm/metadata/default.meta: -------------------------------------------------------------------------------- 1 | 2 | # Application-level permissions 3 | 4 | [] 5 | access = read : [ * ], write : [ admin, power ] 6 | 7 | ### EVENT TYPES 8 | 9 | [eventtypes] 10 | export = system 11 | 12 | 13 | ### PROPS 14 | 15 | [props] 16 | export = system 17 | 18 | 19 | ### TRANSFORMS 20 | 21 | [transforms] 22 | export = system 23 | 24 | 25 | ### LOOKUPS 26 | 27 | [lookups] 28 | export = system 29 | 30 | 31 | ### VIEWSTATES: even normal users should be able to create shared viewstates 32 | 33 | [viewstates] 34 | access = read : [ * ], write : [ * ] 35 | export = system 36 | 37 | 38 | [alert_actions] 39 | export = system 40 | 41 | [alerts] 42 | export = system 43 | 44 | [restmap] 45 | export = system 46 | -------------------------------------------------------------------------------- /Python/connectors/splunk/screenshot/lib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Python/connectors/splunk/screenshot/lib.png -------------------------------------------------------------------------------- /Python/extension_query_sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Python/extension_query_sample.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cbe-rest-api 2 | 3 | Use the [Chrome Browser Enterprise (CBE)](https://support.google.com/chrome/a/topic/9025410?hl=en&ref_topic=4386754) REST API to manage the Chrome browser in your orgnization. 4 | 5 | ## Documentation 6 | * [Getting started with CEC API > start here](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/API_Get_Started.md) 7 | * [Scopes](docs/auth.md) 8 | * APIs 9 | * [App Details API](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/App_Details_api.md) 10 | * [Chrome Enterprise Core API](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/CBCM_api.md) 11 | * [Chrome Management API](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/Chrome_Management_Reports_api.md) 12 | * [Chrome Policy API](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/Chrome_Policy_api.md) 13 | * [Directory API](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/Directory_api.md) 14 | * [Enrollment Token API](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/Enrollment_Token_api.md) 15 | * [Reports API](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/Reports_api.md) 16 | * Postman 17 | * [Using Postman for CBCM API calls](https://github.com/google/ChromeBrowserEnterprise/blob/main/postman/README.md) 18 | * [Postman collection](https://www.postman.com/google-chrome-enterprise-apis/workspace/google-chrome-enterprise-public/overview) - requests that utilizes the above mentioned APIs. 19 | * PowerShell 20 | * [Random Scripts](https://github.com/google/ChromeBrowserEnterprise/tree/main/Windows/PowerShell) - scripts to wake the browser and force browser to update. 21 | * [Random CBCM Scripts](https://github.com/google/ChromeBrowserEnterprise/tree/main/Windows/PowerShell/cbcm) - script to add the enrollment token to the device and launch the browesr (complete the enrollment process). 22 | 23 | 24 | ## Contributing 25 | See [CONTRIBUTING.md](CONTRIBUTING.md) for details. 26 | 27 | ## License 28 | See [LICENSE](LICENSE) for details. 29 | -------------------------------------------------------------------------------- /Windows/PinChromeToTaskbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Windows/PowerShell/CommandAs/WakeBrowserAsSystem.ps1: -------------------------------------------------------------------------------- 1 | #Requirement - https://github.com/mkellerman/Invoke-CommandAs 2 | Install-Module -Name Invoke-CommandAs -Force 3 | 4 | #print enrollment token 5 | #Get-ItemProperty -Path HKLM:\SOFTWARE\Policies\Google\Chrome -Name "CloudManagementEnrollmentToken" 6 | 7 | # Execute As System. Launch chrome browser as system in a temp data dir. 8 | Write-Output "Launch the browser" 9 | Invoke-CommandAs -ScriptBlock { 10 | # set chrome user data dir. 11 | $chromeUserDataDir = "c:/temp3/cbcmLauncher" 12 | #Write-Output $chromeUserDataDir 13 | 14 | # set a name for the chrome profile. 15 | $chromeProfile = "cbcmProfile" 16 | #Write-Output $chromeProfile 17 | 18 | $chromepaths = $chromeUserDataDir, $chromeUserDataDir + "\" + $chromeProfile 19 | 20 | # construct the chrome arg list. 21 | $chromeArgList = "--user-data-dir=""" + $chromeUserDataDir + """ --profile-directory=""" + $chromeProfile + """" 22 | #Write-Output $chromeArgList 23 | Start-Process "chrome.exe" -ArgumentList $chromeArgList 24 | } -AsSystem 25 | 26 | Start-Sleep -Seconds 45 27 | 28 | # Execute As System - Find chrome processes running as system and stop the process. 29 | Write-Output "Stop the browser" 30 | Invoke-CommandAs -ScriptBlock { 31 | Get-Process -Name chrome -IncludeUserName | Where UserName -match system | Stop-Process -Force 32 | } -AsSystem 33 | 34 | # wait for the chrome processes to stop. 35 | Start-Sleep -Seconds 15 36 | 37 | # clean up chrome user data dir. 38 | Write-Output "Clean up work" 39 | $chromeUserDataDir = "c:/temp3" 40 | if (Test-Path -Path $chromeUserDataDir) { 41 | Remove-Item $chromeUserDataDir -Recurse 42 | } 43 | -------------------------------------------------------------------------------- /Windows/PowerShell/Delete-ChromeRegistry.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Recursively deletes a specified registry key after checking for its existence. 4 | 5 | .DESCRIPTION 6 | This script targets the "HKEY_CURRENT_USER\Software\Google\Chrome" registry path. 7 | It first verifies if the key exists. If it does, the script deletes the key 8 | and all of its subkeys and values. All actions, successes, and errors are 9 | logged to a text file in the script's execution directory. 10 | 11 | .NOTES 12 | Execution Policy: You may need to change PowerShell's execution policy to run the script. Open PowerShell as an Administrator and run the following command: 13 | Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process 14 | Run this script with appropriate permissions. Incorrect use can affect system stability. 15 | After running the script, a file named Registry-Deletion-Log.txt will appear in the same directory. 16 | b/430559703 17 | #> 18 | 19 | #--- Script Configuration --- 20 | 21 | # Set the target registry path. HKCU: is the PowerShell alias for HKEY_CURRENT_USER. 22 | $RegistryPath = "HKCU:\Software\Google\Chrome" 23 | 24 | # Define the name for the log file. 25 | $LogFileName = "Registry-Deletion-Log.txt" 26 | 27 | # Automatically determine the script's directory and set the full log file path. 28 | # $PSScriptRoot is an automatic variable that contains the directory of the script. 29 | $LogFilePath = Join-Path -Path $PSScriptRoot -ChildPath $LogFileName 30 | 31 | #--- Script Execution --- 32 | 33 | # Start a transcript to log all console output to the specified file. 34 | # -Append will add to the log file if it already exists. 35 | Start-Transcript -Path $LogFilePath -Append 36 | 37 | # Get the current timestamp for logging purposes. 38 | $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" 39 | Write-Host "[$Timestamp] --- Starting Registry Deletion Script ---" 40 | Write-Host "[$Timestamp] Target Key: $RegistryPath" 41 | Write-Host "[$Timestamp] Log File Location: $LogFilePath" 42 | Write-Host "" # Add a blank line for readability. 43 | 44 | # Check if the registry path exists before attempting any action. 45 | if (Test-Path -Path $RegistryPath) { 46 | Write-Host "[$Timestamp] [INFO] Registry key found at '$RegistryPath'." 47 | 48 | # Use a try...catch block to handle potential errors during deletion (e.g., permissions issues). 49 | try { 50 | Write-Host "[$Timestamp] [ACTION] Attempting to recursively delete the key..." 51 | 52 | # -Recurse deletes all child items. -Force attempts to remove items that can't otherwise be deleted. 53 | # -ErrorAction Stop ensures that any error will trigger the catch block immediately. 54 | Remove-Item -Path $RegistryPath -Recurse -Force -ErrorAction Stop 55 | 56 | Write-Host "[$Timestamp] [SUCCESS] Successfully deleted registry key and all its contents." 57 | } 58 | catch { 59 | # This block runs if an error occurs in the 'try' block. 60 | # $_ represents the error object. 61 | Write-Error "[$Timestamp] [ERROR] Failed to delete registry key. Details below." 62 | Write-Error $_ 63 | } 64 | } 65 | else { 66 | # This block runs if Test-Path returns false. 67 | Write-Host "[$Timestamp] [INFO] Registry key not found. No action required." 68 | } 69 | 70 | Write-Host "" # Add a blank line for readability. 71 | Write-Host "[$Timestamp] --- Script Execution Finished ---" 72 | 73 | # Stop the transcript to save and close the log file. 74 | Stop-Transcript 75 | -------------------------------------------------------------------------------- /Windows/PowerShell/ForceUpdateBrowser.ps1: -------------------------------------------------------------------------------- 1 | # Force the browser to update 2 | Start-Process -Filepath cscript.exe -WorkingDirectory "c:\temp" -ArgumentList "update3web_demo.js {8A69D345-D564-463c-AFF1-A69D9E530F96} 1 3" -wait -RedirectStandardOutput "c:\temp\chrome_update.txt" 3 | 4 | #Suspends the activity in the script for 60 sec for update to complete 5 | Start-Sleep -Seconds 60 6 | 7 | # Execute As System. Launch chrome browser as system in a temp data dir. 8 | Write-Output "Launch the browser" 9 | Invoke-Command -ScriptBlock { 10 | # set chrome user data dir. 11 | $chromeUserDataDir = "c:/temp3/cbcmLauncher" 12 | #Write-Output $chromeUserDataDir 13 | 14 | # set a name for the chrome profile. 15 | $chromeProfile = "cbcmProfile" 16 | #Write-Output $chromeProfile 17 | 18 | $chromepaths = $chromeUserDataDir, $chromeUserDataDir + "\" + $chromeProfile 19 | 20 | # construct the chrome arg list. 21 | $chromeArgList = "--user-data-dir=""" + $chromeUserDataDir + """ --profile-directory=""" + $chromeProfile + """" 22 | #Write-Output $chromeArgList 23 | Start-Process "chrome.exe" -ArgumentList $chromeArgList 24 | } 25 | 26 | Start-Sleep -Seconds 45 27 | 28 | # Execute As System - Find chrome processes running as system and stop the process. 29 | Write-Output "Stop the browser" 30 | Invoke-Command -ScriptBlock { 31 | Get-Process -Name chrome -IncludeUserName | Where UserName -match system | Stop-Process -Force 32 | } 33 | 34 | # wait for the chrome processes to stop. 35 | Start-Sleep -Seconds 15 36 | 37 | # clean up chrome user data dir. 38 | Write-Output "Clean up work" 39 | $chromeUserDataDir = "c:/temp3" 40 | if (Test-Path -Path $chromeUserDataDir) { 41 | Remove-Item $chromeUserDataDir -Recurse 42 | } 43 | -------------------------------------------------------------------------------- /Windows/PowerShell/MoveBookmarksBetweenProfiles.ps1: -------------------------------------------------------------------------------- 1 | $SourceProfile = "Default" # Replace with the actual source profile name (e.g., "Profile 1") 2 | $TargetProfile = "Profile 2" # Replace with the actual target profile name 3 | 4 | # Get Chrome's User Data directory path 5 | $UserDataPath = [Environment]::GetFolderPath("LocalApplicationData") + "\Google\Chrome\User Data" 6 | 7 | # Construct paths to Bookmarks files 8 | $SourceBookmarksPath = "$UserDataPath\$SourceProfile\Bookmarks" 9 | $TargetBookmarksPath = "$UserDataPath\$TargetProfile\Bookmarks" 10 | 11 | # Ensure source profile and Bookmarks file exist 12 | if (!(Test-Path $SourceBookmarksPath)) { 13 | Write-Error "Source profile or Bookmarks file not found." 14 | exit 1 15 | } 16 | 17 | # Backup the target profile's Bookmarks (optional but recommended) 18 | if (Test-Path $TargetBookmarksPath) { 19 | $BackupPath = $TargetBookmarksPath + ".bak" 20 | Copy-Item $TargetBookmarksPath $BackupPath 21 | } 22 | 23 | # Copy Bookmarks from source to target 24 | Copy-Item $SourceBookmarksPath $TargetBookmarksPath 25 | 26 | Write-Output "Bookmarks transferred successfully from '$SourceProfile' to '$TargetProfile'." 27 | -------------------------------------------------------------------------------- /Windows/PowerShell/README.md: -------------------------------------------------------------------------------- 1 | # Random Scripts 2 | ## Wake Browser 3 | Consider using the [wake browser script](/Windows/PowerShell/WakeBrowser.ps1) to run Chrome silently under the System context to allow version data to update to the Windows registry. 4 | 5 | ``` 6 | .\WakeBrowser.ps1 7 | ``` 8 | 9 | ## Force Update 10 | You can force an update to the browser and run Chrome silently under the System context to allow version data to update to the Windows registry. 11 | 12 | [legacy_update3web.js](https://source.chromium.org/chromium/chromium/src/+/main:chrome/updater/win/test/legacy_update3web.js) from the [Google Omaha team](https://github.com/google/omaha/tree/main/omaha/tools/performondemand) :heart:. 13 | 14 | ``` 15 | cscript legacy_update3web.js {8A69D345-D564-463c-AFF1-A69D9E530F96} 1 3 16 | ``` 17 | 18 | update3web_demo.js script takes three arguments: 19 | 20 | arg[0] {8A69D345-D564-463c-AFF1-A69D9E530F96} is the Chrome Stable product guid. 21 | 22 | arg[1] 1 applies to the Machine. 23 | 24 | arg[2] 3 perform an Update. 25 | 26 | 27 | ## Disable Edge default browser settings campaigns 28 | Use the [disableEdgeDefaultBrowserSettingsCampaigns](/Windows/PowerShell/disableEdgeDefaultBrowserSettingsCampaigns.ps1) script to decline the Microsoft Edge default browser and/or default search engine campaigns. With the [DefaultBrowserSettingsCampaignEnabled](https://learn.microsoft.com/en-us/deployedge/microsoft-edge-policies#defaultbrowsersettingscampaignenabled) policy set to disabled, users will not be prompted to set Microsoft Edge as the default browser, or to set Microsoft Bing as the default search engine. 29 | 30 | ``` 31 | .\disableEdgeDefaultBrowserSettingsCampaigns.ps1 32 | ``` 33 | 34 | ## Unenroll a browser 35 | You can unenroll a browser from the local endpoint by running the [Unenroll-from-CBCM.cmd](/Windows/PowerShell/Unenroll-from-CBCM.cmd) from an administrator mode shell. 36 | 37 | 38 | 39 | 40 | ``` 41 | Unenroll-from-CBCM.cmd 42 | ``` 43 | -------------------------------------------------------------------------------- /Windows/PowerShell/Unenroll-from-CBCM.cmd: -------------------------------------------------------------------------------- 1 | :: This script will unenroll the Chrome browser from Chrome Browser Cloud Mgmt (CBCM) console by removing the : 2 | :: CloudManagementEnrollmentToken 3 | :: Device token 4 | :: Note: You must delete the enrolled browser from CBCM in the Google Admin Console. 5 | :: Use adminstrator mode when running this script in command prompt. 6 | 7 | :: Remove CloudManagementEnrollmentToken 8 | reg delete "HKLM\SOFTWARE\Policies\Google\Chrome" /v "CloudManagementEnrollmentToken" /f 9 | 10 | :: Remove Device token 11 | reg delete "HKLM\SOFTWARE\Google\Chrome\Enrollment" /f 12 | reg delete "HKLM\SOFTWARE\WOW6432Node\Google\Enrollment" /f 13 | 14 | ::Delete the directory where Google Update writes cached cloud policies 15 | rmdir /s /q "C:\Program Files (x86)\Google\Policies" 16 | -------------------------------------------------------------------------------- /Windows/PowerShell/WakeBrowser.ps1: -------------------------------------------------------------------------------- 1 | # Execute As System. Launch chrome browser as system in a temp data dir. 2 | Write-Output "Launch the browser" 3 | 4 | # set chrome user data dir. 5 | $chromeUserDataDir = "c:/temp/ChromeLauncherProfile" 6 | #Write-Output $chromeUserDataDir 7 | 8 | # set a name for the chrome profile. 9 | $chromeProfile = "CECProfile" 10 | #Write-Output $chromeProfile 11 | 12 | $chromepaths = $chromeUserDataDir, $chromeUserDataDir + "\" + $chromeProfile 13 | 14 | # construct the chrome arg list. 15 | $chromeArgList = "--user-data-dir=""" + $chromeUserDataDir + """ --profile-directory=""" + $chromeProfile + """" 16 | #Write-Output $chromeArgList 17 | Start-Process "chrome.exe" -ArgumentList $chromeArgList 18 | 19 | Start-Sleep -Seconds 45 20 | 21 | # Execute As System - Find chrome processes running as system and stop the process. 22 | Write-Output "Stop the browser" 23 | 24 | Get-Process -Name chrome -IncludeUserName | Where UserName -match system | Stop-Process -Force 25 | 26 | # wait for the chrome processes to stop. 27 | Start-Sleep -Seconds 15 28 | 29 | # clean up chrome user data dir. 30 | Write-Output "Clean up work" 31 | 32 | if (Test-Path -Path $chromeUserDataDir) { 33 | # Folder exists, so delete it and its contents 34 | Remove-Item -Path $chromeUserDataDir -Recurse -Force 35 | Write-Host "Folder '$chromeUserDataDir' and its contents have been deleted." 36 | } 37 | -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/AddEnrollmentTokenThenRegister.ps1: -------------------------------------------------------------------------------- 1 | 2 | #add enrollment token 3 | Write-Output "enrollment token" 4 | Invoke-Command -ScriptBlock { 5 | # policy doc - https://chromeenterprise.google/policies/#CloudManagementEnrollmentToken 6 | #The value of this policy is an enrollment token you can retrieve from the Google Admin console. 7 | $enrollmentToken = '' 8 | 9 | #validate Google policy path 10 | $GoogleRegistryPath = 'HKLM:\SOFTWARE\Policies\Google' 11 | $test = test-path -path $GoogleRegistryPath 12 | 13 | #create if the required path doesn't exist 14 | if(-not($test)){ 15 | New-Item -Path $GoogleRegistryPath 16 | } 17 | 18 | #validate Google/Chrome policy path 19 | $GoogleChromeRegistryPath = $GoogleRegistryPath + '\Chrome' 20 | $test = test-path -path $GoogleChromeRegistryPath 21 | 22 | #create if the required path doesn't exist 23 | if(-not($test)){ 24 | New-Item -Path $GoogleChromeRegistryPath 25 | } 26 | 27 | #The enrollment token of cloud policy 28 | $keyName = 'CloudManagementEnrollmentToken' 29 | 30 | $member = (Get-Item $GoogleChromeRegistryPath).Property -contains $keyName 31 | 32 | if( $member ) { 33 | Set-ItemProperty -Path $GoogleChromeRegistryPath -Name $keyName -Value $enrollmentToken 34 | } 35 | else { 36 | New-ItemProperty -Path $GoogleChromeRegistryPath -Name $keyName -PropertyType String -Value $enrollmentToken 37 | } 38 | } 39 | 40 | #print enrollment token 41 | #Get-ItemProperty -Path HKLM:\SOFTWARE\Policies\Google\Chrome -Name "CloudManagementEnrollmentToken" 42 | 43 | # Execute As System. Launch chrome browser as system in a temp data dir. 44 | Write-Output "Launch the browser" 45 | Invoke-Command -ScriptBlock { 46 | # set chrome user data dir. 47 | $chromeUserDataDir = "c:/temp3/cbcmLauncher" 48 | #Write-Output $chromeUserDataDir 49 | 50 | # set a name for the chrome profile. 51 | $chromeProfile = "cbcmProfile" 52 | #Write-Output $chromeProfile 53 | 54 | $chromepaths = $chromeUserDataDir, $chromeUserDataDir + "\" + $chromeProfile 55 | 56 | # construct the chrome arg list. 57 | $chromeArgList = "--user-data-dir=""" + $chromeUserDataDir + """ --profile-directory=""" + $chromeProfile + """" 58 | #Write-Output $chromeArgList 59 | Start-Process "chrome.exe" -ArgumentList $chromeArgList 60 | } 61 | 62 | Start-Sleep -Seconds 45 63 | 64 | # Execute As System - Find chrome processes running as system and stop the process. 65 | Write-Output "Stop the browser" 66 | Invoke-Command -ScriptBlock { 67 | Get-Process -Name chrome -IncludeUserName | Where UserName -match system | Stop-Process -Force 68 | } 69 | 70 | # wait for the chrome processes to stop. 71 | Start-Sleep -Seconds 15 72 | 73 | # clean up chrome user data dir. 74 | Write-Output "Clean up work" 75 | $chromeUserDataDir = "c:/temp3" 76 | if (Test-Path -Path $chromeUserDataDir) { 77 | Remove-Item $chromeUserDataDir -Recurse 78 | } 79 | -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/CommandAs/AddEnrollmentTokenThenRegisterAsSystem.ps1: -------------------------------------------------------------------------------- 1 | #Requirement - https://github.com/mkellerman/Invoke-CommandAs 2 | Install-Module -Name Invoke-CommandAs -Force 3 | 4 | #add enrollment token 5 | Write-Output "enrollment token" 6 | Invoke-CommandAs -ScriptBlock { 7 | # policy doc - https://chromeenterprise.google/policies/#CloudManagementEnrollmentToken 8 | #The value of this policy is an enrollment token you can retrieve from the Google Admin console. 9 | $enrollmentToken = '' 10 | 11 | #validate Google policy path 12 | $GoogleRegistryPath = 'HKLM:\SOFTWARE\Policies\Google' 13 | $test = test-path -path $GoogleRegistryPath 14 | 15 | #create if the required path doesn't exist 16 | if(-not($test)){ 17 | New-Item -Path $GoogleRegistryPath 18 | } 19 | 20 | #validate Google/Chrome policy path 21 | $GoogleChromeRegistryPath = $GoogleRegistryPath + '\Chrome' 22 | $test = test-path -path $GoogleChromeRegistryPath 23 | 24 | #create if the required path doesn't exist 25 | if(-not($test)){ 26 | New-Item -Path $GoogleChromeRegistryPath 27 | } 28 | 29 | #The enrollment token of cloud policy 30 | $keyName = 'CloudManagementEnrollmentToken' 31 | 32 | $member = (Get-Item $GoogleChromeRegistryPath).Property -contains $keyName 33 | 34 | if( $member ) { 35 | Set-ItemProperty -Path $GoogleChromeRegistryPath -Name $keyName -Value $enrollmentToken 36 | } 37 | else { 38 | New-ItemProperty -Path $GoogleChromeRegistryPath -Name $keyName -PropertyType String -Value $enrollmentToken 39 | } 40 | } -AsSystem 41 | 42 | #print enrollment token 43 | #Get-ItemProperty -Path HKLM:\SOFTWARE\Policies\Google\Chrome -Name "CloudManagementEnrollmentToken" 44 | 45 | # Execute As System. Launch chrome browser as system in a temp data dir. 46 | Write-Output "Launch the browser" 47 | Invoke-CommandAs -ScriptBlock { 48 | # set chrome user data dir. 49 | $chromeUserDataDir = "c:/temp3/cbcmLauncher" 50 | #Write-Output $chromeUserDataDir 51 | 52 | # set a name for the chrome profile. 53 | $chromeProfile = "cbcmProfile" 54 | #Write-Output $chromeProfile 55 | 56 | $chromepaths = $chromeUserDataDir, $chromeUserDataDir + "\" + $chromeProfile 57 | 58 | # construct the chrome arg list. 59 | $chromeArgList = "--user-data-dir=""" + $chromeUserDataDir + """ --profile-directory=""" + $chromeProfile + """" 60 | #Write-Output $chromeArgList 61 | Start-Process "chrome.exe" -ArgumentList $chromeArgList 62 | } -AsSystem 63 | 64 | Start-Sleep -Seconds 45 65 | 66 | # Execute As System - Find chrome processes running as system and stop the process. 67 | Write-Output "Stop the browser" 68 | Invoke-CommandAs -ScriptBlock { 69 | Get-Process -Name chrome -IncludeUserName | Where UserName -match system | Stop-Process -Force 70 | } -AsSystem 71 | 72 | # wait for the chrome processes to stop. 73 | Start-Sleep -Seconds 15 74 | 75 | # clean up chrome user data dir. 76 | Write-Output "Clean up work" 77 | $chromeUserDataDir = "c:/temp3" 78 | if (Test-Path -Path $chromeUserDataDir) { 79 | Remove-Item $chromeUserDataDir -Recurse 80 | } 81 | -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/MoveEnrolledBrowserByWindowsOSName.ps1: -------------------------------------------------------------------------------- 1 | #Define Variables 2 | $scriptFolder = Split-Path ($MyInvocation.MyCommand.Path) -Parent 3 | 4 | #Configure NuGet and then download required libraries 5 | if (Get-PackageProvider -Name NuGet) { 6 | Copy-WriteToLog -logString "NuGet is installed" 7 | } 8 | else { 9 | register-packagesource -Name NuGet -ProviderName NuGet -location https://www.nuget.org/api/v2/ 10 | } 11 | 12 | #https://www.nuget.org/packages/Newtonsoft.Json/13.0.1 13 | Install-Package Newtonsoft.Json -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '13.0.1' -SkipDependencies -ErrorAction SilentlyContinue 14 | #https://www.nuget.org/packages/Google.Apis.Core/1.57.0 15 | Install-Package Google.Apis.Core -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 16 | #https://www.nuget.org/packages/Google.Apis/1.57.0 17 | Install-Package Google.Apis -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 18 | #https://www.nuget.org/packages/Google.Apis.Auth/1.57.0 19 | Install-Package Google.Apis.Auth -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 20 | 21 | 22 | 23 | #/******* Required Add Types for Google APIs *******/ 24 | Add-Type -Path "$scriptFolder\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll" 25 | 26 | Add-Type -Path "$scriptFolder\Google.Apis.Core.1.57.0\lib\net45\Google.Apis.Core.dll" 27 | 28 | Add-Type -Path "$scriptFolder\Google.Apis.1.57.0\lib\net45\Google.Apis.dll" 29 | 30 | Add-Type -Path "$scriptFolder\Google.Apis.Auth.1.57.0\lib\net45\Google.Apis.Auth.dll" 31 | 32 | #/******* BEGIN: Customer to modify this section *******/ 33 | $customerId = '' 34 | $machineName = $env:computername 35 | $secretFile = '' 36 | $org_unit_path = '' 37 | #/******* END: Customer to modify this section *******/ 38 | 39 | 40 | #/******* Unenrolling a browser from CBCM *******/ 41 | function Set-EnrolledBrowser 42 | { 43 | param ( 44 | [Parameter(Mandatory)] [string]$CustomerId, 45 | 46 | [Parameter(Mandatory)] [string]$MachineName, 47 | 48 | [Parameter(Mandatory)] [string]$SecretFile, 49 | 50 | [Parameter(Mandatory)] [string]$OrgUnitPath 51 | ) 52 | 53 | $response = "" 54 | 55 | try 56 | { 57 | $qualified = Get-IsWindowsLTSC 58 | 59 | if (-Not $qualified) { 60 | return "Does not qualify." 61 | } 62 | 63 | $authToken = Get-GoogleToken -SecretFile $SecretFile 64 | 65 | $bearerToken = [string]::Format(“Bearer {0}”, $authToken) 66 | 67 | $deviceId = Get-EnrolledBrowser -Token $bearerToken -CustomerId $CustomerId -MachineName $MachineName 68 | 69 | $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 70 | $headers.Add("Authorization", [string]::Format(“{0}”, $bearerToken)) 71 | $headers.Add("Content-Type", "application/json") 72 | 73 | $body = "{`"org_unit_path`":`"$OrgUnitPath`",`"resource_ids`":[`"$deviceId`"]}" 74 | 75 | [string]$requestURL = [string]::Format(“https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers/moveChromeBrowsersToOu”,$CustomerId) 76 | 77 | $response = Invoke-RestMethod $requestURL -Method 'POST' -Headers $headers -Body $body 78 | $response | ConvertTo-Json 79 | 80 | Copy-WriteToLog -logString $response.ToString() 81 | } 82 | catch [System.Net.WebException] { 83 | Copy-WriteToLog -logString $_.Exception + "\r\n" + ($_.Exception.Response.StatusCode.value__ ).ToString().Trim() + "\r\n" + ($_.Exception.Message).ToString().Trim() + "\r\n" + ($_.Exception.TargetSite).ToString().Trim() 84 | } catch { 85 | Copy-WriteToLog -logString $_.Exception 86 | } 87 | 88 | 89 | return $response 90 | } 91 | 92 | #/******* What version of Windows am I running? *******/ 93 | function Get-IsWindowsLTSC 94 | { 95 | # get OS name information. Ref: https://learn.microsoft.com/en-us/windows/client-management/windows-version-search 96 | $osName = systeminfo | findstr /B /C:"OS Name" /B 97 | 98 | if (($osName -like "*LTSB*") -or ($osName -like "*LTSC*")){ 99 | return $true 100 | } 101 | 102 | return $false 103 | } 104 | 105 | 106 | #/******* Get the device Id from the enrolled browser *******/ 107 | function Get-EnrolledBrowser 108 | { 109 | param ( 110 | [Parameter(Mandatory)] [Object[]]$Token, 111 | 112 | [Parameter(Mandatory)] [string]$CustomerId, 113 | 114 | [Parameter(Mandatory)] [string]$MachineName 115 | ) 116 | $deviceId = "" 117 | try 118 | { 119 | 120 | $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 121 | $headers.Add("Authorization", [string]::Format(“{0}”, $Token)) 122 | [string]$requestURL = [string]::Format(“https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers?query=machine_name:{1}&projection=BASIC”,$CustomerId, $MachineName) 123 | 124 | $response = Invoke-RestMethod $requestURL -Method 'GET' -Headers $headers 125 | 126 | $deviceId = $response.browsers[0].deviceId 127 | Copy-WriteToLog -logString "The device ID is $($deviceId)" 128 | } 129 | catch 130 | { 131 | Copy-WriteToLog -logString $_.Exception.Message 132 | } 133 | 134 | return $deviceId 135 | 136 | } 137 | 138 | 139 | #/******* Get Auth Token *******/ 140 | function Get-GoogleToken 141 | { 142 | param ( 143 | [Parameter(Mandatory)] [string]$SecretFile 144 | ) 145 | $token = '' 146 | try 147 | { 148 | $JsonFilePath = $SecretFile 149 | $scopes = New-Object -TypeName System.Collections.Generic.List[string] 150 | #add additional scope to the collection 151 | $scopes.Add('https://www.googleapis.com/auth/admin.directory.device.chromebrowsers') 152 | 153 | $googleCred = [Google.Apis.Auth.OAuth2.GoogleCredential]::FromFile($JsonFilePath) 154 | $googleCred = $googleCred.CreateScoped($scopes) 155 | 156 | $token = ([Google.Apis.Auth.OAuth2.ITokenAccess]$googleCred).GetAccessTokenForRequestAsync().GetAwaiter().GetResult() 157 | Copy-WriteToLog -logString "The token is $($token)" 158 | 159 | } 160 | catch 161 | { 162 | Copy-WriteToLog -logString $_.Exception.Message 163 | } 164 | 165 | return $token 166 | } 167 | 168 | #/******* Write to a local log fle *******/ 169 | function Copy-WriteToLog 170 | { 171 | Param ( 172 | [string]$logString 173 | ) 174 | 175 | $logfile = $scriptFolder + "\" + "MoveBrowser.txt" 176 | $stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss") 177 | $logMessage = "$stamp $logString" 178 | Add-content $logfile -value $logMessage 179 | } 180 | 181 | 182 | #/******* BEGIN: main *******/ 183 | Set-EnrolledBrowser -CustomerId $customerId -MachineName $machineName -SecretFile $secretFile -OrgUnitPath $org_unit_path 184 | #/******* END: rmain *******/ 185 | -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/MoveReEnrollBrowser.ps1: -------------------------------------------------------------------------------- 1 | #/******* Start: Move browsers between OUs using the CBCM enrollment token *******/ 2 | #The value of this policy is an enrollment token you can retrieve from the Google Admin console. 3 | $enrollmentToken = '' 4 | 5 | #/******* Write to a local log fle *******/ 6 | function Copy-WriteToLog 7 | { 8 | Param ( 9 | [string]$logString 10 | ) 11 | 12 | $logfile = $scriptFolder + "\" + "MoveReEnrollBrowser_log.txt" 13 | $stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss") 14 | $logMessage = "$stamp $logString" 15 | Add-content $logfile -value $logMessage 16 | } 17 | 18 | #/******* Test registry value *******/ 19 | Function Test-RegistryValue ($regkey, $name) { 20 | if (Get-ItemProperty -Path $regkey -Name $name -ErrorAction Ignore) { 21 | return $true 22 | } else { 23 | return $false 24 | } 25 | } 26 | 27 | $GoogleChromeRegistryPath = 'HKLM:\SOFTWARE\Policies\Google\Chrome' 28 | #The enrollment token of cloud policy 29 | $keyName = 'CloudManagementEnrollmentToken' 30 | 31 | #chrome browser cloud enrollment token 32 | if ((Test-RegistryValue $GoogleChromeRegistryPath 'CloudManagementEnrollmentToken')) 33 | { 34 | Set-ItemProperty -Path $GoogleChromeRegistryPath -Name $keyName -Value $enrollmentToken 35 | Copy-WriteToLog -logString "Cloud Management Enrollment Token Updated" 36 | } 37 | 38 | $dmTokenInRegularHive = 'HKLM:\SOFTWARE\Google\Chrome\Enrollment' 39 | 40 | #device management token from regular hive 41 | if ((Test-RegistryValue $dmTokenInRegularHive 'dmtoken')) 42 | { 43 | Remove-Item $dmTokenInRegularHive 44 | Copy-WriteToLog -logString "dmtoken deleted from regular hive" 45 | } 46 | 47 | $dmTokenInWOWHive = 'HKLM:\SOFTWARE\WOW6432Node\Google\Enrollment' 48 | 49 | #device management token from WOW6432Node hive 50 | if ((Test-RegistryValue $dmTokenInWOWHive 'dmtoken')) 51 | { 52 | Remove-Item $dmTokenInWOWHive 53 | Copy-WriteToLog -logString "dmtoken deleted from WOW6432Node hive" 54 | } 55 | 56 | 57 | #/******* END: Move browsers between OUs using the CBCM enrollment token *******/ -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/README.md: -------------------------------------------------------------------------------- 1 | # Random CBCM Scripts 2 | ## Enroll the browser 3 | Consider using the [Add Enrollment Token then Register script](AddEnrollmentTokenThenRegister.ps1) to set the [CloudManagementEnrollmentToken](https://chromeenterprise.google/policies/#CloudManagementEnrollmentToken) to register the browser with Chrome Browser Cloud Management (CBCM). In order to complete the registration process, the script should run under the System context. 4 | 5 | **Note:** Insert the enrollment token from the Google Admin console in [line](AddEnrollmentTokenThenRegister.ps1#L9) before running the script. 6 | 7 | ``` 8 | .\AddEnrollmentTokenThenRegister.ps1 9 | ``` 10 | 11 | ## Move browsers between OU using enrollment token 12 | Consider using the [Move Re-enroll Browser script](MoveReEnrollBrowser.ps1) to move enrolled browsers between OUs based on the enrollment token. In order to update registry settings, the script should run under the System context. 13 | 14 | This feature is only available via an allowlist - please contaact your Chrome Browser Enterprise team to add your domain to the allowlist. 15 | 16 | **Note:** Insert the enrollment token from the Google Admin console in [line](MoveReEnrollBrowser.ps1#L3) before running the script. 17 | 18 | ``` 19 | .\MoveReEnrollBrowser.ps1 20 | ``` 21 | 22 | ## Unenroll the browser 23 | Consider using the [Unenroll Browser script](UnenrollBrowser.ps1) to unenroll a browser from CBCM and delete the CloudManagementEnrollmentToken and device management token from the device. Unenrolling devices from CBCM also deletes the already uploaded data to the Admin console. Platform policies and cloud-based user policies are not affected. 24 | 25 | **Note:** You will need to add the customer ID and the OAuth key JSON file to the script to allow an API call to delete an enrolled browser. Run the script from devices that should be unenrolled. 26 | 27 | :point_right: Add the customer id [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/ps/src/cbcm/UnenrollBrowser.ps1#L159). You can find the customer Id by navigating to the [Google Admin Console](https://admin.google.com) > Account > Account Settings. 28 | 29 | :point_right: Add the path to the OAuth client secret file [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/ps/src/cbcm/UnenrollBrowser.ps1#L161). You can download the file from the [Google Developer Console](https://console.developers.google.com/apis/api/admin.googleapis.com/overview?project=_) 30 | 31 | 32 | ``` 33 | .\UnenrollBrowser.ps1 34 | ``` 35 | 36 | ## Move Chrome browsers between Organization Units 37 | Consider using the [Move enrolled browser by Windows OS Name](MoveEnrolledBrowserByWindowsOSName.ps1) to move enrolled browser between Organization Units (OU). The script performs the move if the Windows OS is qualifies as [Long-Term Servicing Channel (LTSC, formerly LTSB)](https://learn.microsoft.com/en-us/windows/client-management/windows-version-search). However, you can change the qualification rule(s) to fit your business needs. 38 | 39 | **Note:** You will need to add the customer ID, the service account key JSON file, and the destination OU path to the script. 40 | 41 | :point_right: Add the customer id [here](https://github.com/google/ChromeBrowserEnterprise/blob/main/ps/src/cbcm/MoveEnrolledBrowserByWindowsOSName.ps1#L33). You can find the customer Id by navigating to the [Google Admin Console](https://admin.google.com) > Account > Account Settings. 42 | 43 | :point_right: Add the path to the OAuth client secret file [here]((https://github.com/google/ChromeBrowserEnterprise/blob/main/ps/src/cbcm/MoveEnrolledBrowserByWindowsOSName.ps1#L48)). You can download the file from the [Google Developer Console](https://console.developers.google.com/apis/api/admin.googleapis.com/overview?project=_) 44 | 45 | :point_right: Add the destination [OU path](https://github.com/google/ChromeBrowserEnterprise/blob/main/ps/src/cbcm/MoveEnrolledBrowserByWindowsOSName.ps1#L50). An example of the destination OU path 'North America/Austin/AUS Managed User' 46 | 47 | 48 | ``` 49 | .\MoveEnrolledBrowserByWindowsOSName.ps1 50 | ``` 51 | 52 | -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/UnenrollBrowser.ps1: -------------------------------------------------------------------------------- 1 | #Define Variables 2 | $scriptFolder = Split-Path ($MyInvocation.MyCommand.Path) -Parent 3 | 4 | #Configure NuGet and then download required libraries 5 | if (Get-PackageProvider -Name NuGet) { 6 | Copy-WriteToLog -logString "NuGet is installed" 7 | } 8 | else { 9 | register-packagesource -Name NuGet -ProviderName NuGet -location https://www.nuget.org/api/v2/ 10 | } 11 | 12 | #https://www.nuget.org/packages/Newtonsoft.Json/13.0.1 13 | Install-Package Newtonsoft.Json -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '13.0.1' -SkipDependencies -ErrorAction SilentlyContinue 14 | #https://www.nuget.org/packages/Google.Apis.Core/1.57.0 15 | Install-Package Google.Apis.Core -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 16 | #https://www.nuget.org/packages/Google.Apis/1.57.0 17 | Install-Package Google.Apis -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 18 | #https://www.nuget.org/packages/Google.Apis.Auth/1.57.0 19 | Install-Package Google.Apis.Auth -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 20 | 21 | 22 | 23 | #/******* Required Add Types for Google APIs *******/ 24 | Add-Type -Path "$scriptFolder\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll" 25 | 26 | Add-Type -Path "$scriptFolder\Google.Apis.Core.1.57.0\lib\net45\Google.Apis.Core.dll" 27 | 28 | Add-Type -Path "$scriptFolder\Google.Apis.1.57.0\lib\net45\Google.Apis.dll" 29 | 30 | Add-Type -Path "$scriptFolder\Google.Apis.Auth.1.57.0\lib\net45\Google.Apis.Auth.dll" 31 | 32 | 33 | 34 | #/******* Unenrolling a browser from CBCM *******/ 35 | function Clear-EnrolledBrowser 36 | { 37 | param ( 38 | [Parameter(Mandatory)] [string]$CustomerId, 39 | 40 | [Parameter(Mandatory)] [string]$MachineName, 41 | 42 | [Parameter(Mandatory)] [string]$SecretFile 43 | ) 44 | 45 | $response = "" 46 | 47 | try 48 | { 49 | $authToken = Get-GoogleToken -SecretFile $SecretFile 50 | 51 | $bearerToken = [string]::Format(“Bearer {0}”, $authToken) 52 | 53 | $deviceId = Get-EnrolledBrowser -Token $bearerToken -CustomerId $CustomerId -MachineName $MachineName 54 | 55 | $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 56 | $headers.Add("Authorization", [string]::Format(“{0}”, $bearerToken)) 57 | 58 | [string]$requestURL = [string]::Format(“https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers/{1}”,$CustomerId, $deviceId) 59 | 60 | $response = Invoke-RestMethod $requestURL -Method 'DELETE' -Headers $headers 61 | $response | ConvertTo-Json 62 | 63 | Copy-WriteToLog -logString $response.ToString() 64 | } 65 | catch 66 | { 67 | Copy-WriteToLog -logString $_.Exception.GetType().FullName + "::" + $_.Exception.Message 68 | } 69 | 70 | return $response 71 | } 72 | 73 | #/******* Get the device Id from the enrolled browser *******/ 74 | function Get-EnrolledBrowser 75 | { 76 | param ( 77 | [Parameter(Mandatory)] [Object[]]$Token, 78 | 79 | [Parameter(Mandatory)] [string]$CustomerId, 80 | 81 | [Parameter(Mandatory)] [string]$MachineName 82 | ) 83 | $deviceId = "" 84 | try 85 | { 86 | 87 | $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 88 | $headers.Add("Authorization", [string]::Format(“{0}”, $Token)) 89 | [string]$requestURL = [string]::Format(“https://www.googleapis.com/admin/directory/v1.1beta1/customer/{0}/devices/chromebrowsers?query=machine_name:{1}&projection=BASIC”,$CustomerId, $MachineName) 90 | 91 | $response = Invoke-RestMethod $requestURL -Method 'GET' -Headers $headers 92 | 93 | $deviceId = $response.browsers[0].deviceId 94 | Copy-WriteToLog -logString "The device ID is $($deviceId)" 95 | } 96 | catch 97 | { 98 | Copy-WriteToLog -logString $_.Exception.Message 99 | } 100 | 101 | return $deviceId 102 | 103 | } 104 | 105 | 106 | #/******* Get Auth Token *******/ 107 | function Get-GoogleToken 108 | { 109 | param ( 110 | [Parameter(Mandatory)] [string]$SecretFile 111 | ) 112 | $token = '' 113 | try 114 | { 115 | $JsonFilePath = $SecretFile 116 | $scopes = New-Object -TypeName System.Collections.Generic.List[string] 117 | #add additional scope to the collection 118 | $scopes.Add('https://www.googleapis.com/auth/admin.directory.device.chromebrowsers') 119 | 120 | $googleCred = [Google.Apis.Auth.OAuth2.GoogleCredential]::FromFile($JsonFilePath) 121 | $googleCred = $googleCred.CreateScoped($scopes) 122 | 123 | $token = ([Google.Apis.Auth.OAuth2.ITokenAccess]$googleCred).GetAccessTokenForRequestAsync().GetAwaiter().GetResult() 124 | Copy-WriteToLog -logString "The token is $($token)" 125 | 126 | } 127 | catch 128 | { 129 | Copy-WriteToLog -logString $_.Exception.Message 130 | } 131 | 132 | return $token 133 | } 134 | 135 | #/******* Write to a local log fle *******/ 136 | function Copy-WriteToLog 137 | { 138 | Param ( 139 | [string]$logString 140 | ) 141 | 142 | $logfile = $scriptFolder + "\" + "UnenrollBrowser.txt" 143 | $stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss") 144 | $logMessage = "$stamp $logString" 145 | Add-content $logfile -value $logMessage 146 | } 147 | 148 | #/******* Test registry value *******/ 149 | Function Test-RegistryValue ($regkey, $name) { 150 | if (Get-ItemProperty -Path $regkey -Name $name -ErrorAction Ignore) { 151 | return $true 152 | } else { 153 | return $false 154 | } 155 | } 156 | 157 | 158 | #/******* BEGIN: Customer to modify this section *******/ 159 | $customerId = '' 160 | $machineName = $env:computername 161 | $secretFile = '' 162 | #/******* END: Customer to modify this section *******/ 163 | 164 | #/******* BEGIN: remove browser from CBCM *******/ 165 | Clear-EnrolledBrowser -CustomerId $customerId -MachineName $machineName -SecretFile $secretFile 166 | #/******* END: remove browser from CBCM *******/ 167 | 168 | #/******* BEGIN: cbcm data from local device *******/ 169 | 170 | #CloudManagementEnrollmentToken 171 | if ((Test-RegistryValue 'HKLM:\SOFTWARE\Policies\Google\Chrome', 'CloudManagementEnrollmentToken')) 172 | { 173 | Remove-ItemProperty –Path 'HKLM:\SOFTWARE\Policies\Google\Chrome' –Name 'CloudManagementEnrollmentToken' 174 | Copy-WriteToLog -logString "CloudManagementEnrollmentToken deleted" 175 | } 176 | 177 | #device management token from regular hive 178 | if ((Test-RegistryValue 'HKLM:\SOFTWARE\Google\Chrome\Enrollment' 'dmtoken')) 179 | { 180 | Remove-Item 'HKLM:\SOFTWARE\Google\Chrome\Enrollment' 181 | Copy-WriteToLog -logString "dmtoken deleted from regular hive" 182 | } 183 | 184 | #device management token from WOW6432Node hive 185 | if ((Test-RegistryValue 'HKLM:\SOFTWARE\WOW6432Node\Google\Enrollment' 'dmtoken')) 186 | { 187 | Remove-Item 'HKLM:\SOFTWARE\WOW6432Node\Google\Enrollment' 188 | Copy-WriteToLog -logString "dmtoken deleted from WOW6432Node hive" 189 | } 190 | 191 | #/******* END: cbcm data from local device *******/ 192 | -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/cbcm_get_token_with_json_file.ps1: -------------------------------------------------------------------------------- 1 | #Define Variables 2 | $scriptFolder = Split-Path ($MyInvocation.MyCommand.Path) -Parent 3 | 4 | #Configure NuGet and then download required libraries 5 | if (Get-PackageProvider -Name NuGet) { 6 | Copy-WriteToLog -logString "Version of NuGet installed = " + (Get-PackageProvider -Name NuGet).version 7 | } 8 | else { 9 | register-packagesource -Name NuGet -ProviderName NuGet -location https://www.nuget.org/api/v2/ 10 | } 11 | 12 | #https://www.nuget.org/packages/Newtonsoft.Json/13.0.1 13 | Install-Package Newtonsoft.Json -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '13.0.1' -SkipDependencies -ErrorAction SilentlyContinue 14 | #https://www.nuget.org/packages/Google.Apis.Core/1.57.0 15 | Install-Package Google.Apis.Core -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 16 | #https://www.nuget.org/packages/Google.Apis/1.57.0 17 | Install-Package Google.Apis -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 18 | #https://www.nuget.org/packages/Google.Apis.Auth/1.57.0 19 | Install-Package Google.Apis.Auth -Destination $scriptFolder -Force -Source 'https://www.nuget.org/api/v2' -ProviderName NuGet -RequiredVersion '1.57.0' -SkipDependencies -ErrorAction SilentlyContinue 20 | 21 | 22 | 23 | #/******* Required Add Types for Google APIs *******/ 24 | Add-Type -Path "$scriptFolder\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll" 25 | 26 | Add-Type -Path "$scriptFolder\Google.Apis.Core.1.57.0\lib\net45\Google.Apis.Core.dll" 27 | 28 | Add-Type -Path "$scriptFolder\Google.Apis.1.57.0\lib\net45\Google.Apis.dll" 29 | 30 | Add-Type -Path "$scriptFolder\Google.Apis.Auth.1.57.0\lib\net45\Google.Apis.Auth.dll" 31 | 32 | 33 | 34 | #/******* Get Auth Token *******/ 35 | function Get-GoogleToken 36 | { 37 | param ( 38 | [Parameter(Mandatory)] [string]$SecretFile 39 | ) 40 | $token = '' 41 | try 42 | { 43 | $JsonFilePath = $scriptFolder + "\" + $SecretFile 44 | $scopes = New-Object -TypeName System.Collections.Generic.List[string] 45 | #add additional scope to the collection 46 | $scopes.Add('https://www.googleapis.com/auth/admin.directory.device.chromebrowsers') 47 | 48 | $googleCred = [Google.Apis.Auth.OAuth2.GoogleCredential]::FromFile($JsonFilePath) 49 | $googleCred = $googleCred.CreateScoped($scopes) 50 | 51 | $token = ([Google.Apis.Auth.OAuth2.ITokenAccess]$googleCred).GetAccessTokenForRequestAsync().GetAwaiter().GetResult() 52 | Copy-WriteToLog -logString "The token is $($token)" 53 | 54 | } 55 | catch 56 | { 57 | Copy-WriteToLog -logString $_.Exception.Message 58 | } 59 | 60 | return $token 61 | } 62 | 63 | #/******* Write to a local log fle *******/ 64 | function Copy-WriteToLog 65 | { 66 | Param ( 67 | [string]$logString 68 | ) 69 | 70 | $logfile = $scriptFolder + "\" + "cbcmLog.txt" 71 | $stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss") 72 | $logMessage = "$stamp $logString" 73 | Add-content $logfile -value $logMessage 74 | } 75 | 76 | 77 | #/******* BEGIN: Customer to modify this section *******/ 78 | $secretFile = '' 79 | #/******* END: Customer to modify this section *******/ 80 | 81 | #/******* BEGIN: Get auth token *******/ 82 | $authToken = Get-GoogleToken -SecretFile $secretFile 83 | -------------------------------------------------------------------------------- /Windows/PowerShell/cbcm/cbcm_get_token_with_json_var.ps1: -------------------------------------------------------------------------------- 1 | #Define Variables 2 | $scriptFolder = Split-Path ($MyInvocation.MyCommand.Path) -Parent 3 | 4 | 5 | #Add Types for Google APIs 6 | 7 | Add-Type -Path "$scriptFolder\Newtonsoft.Json.dll" 8 | 9 | Add-Type -Path "$scriptFolder\Google.Apis.Core.dll" 10 | 11 | Add-Type -Path "$scriptFolder\Google.Apis.Auth.dll" 12 | 13 | Add-Type -Path "$scriptFolder\Google.Apis.dll" 14 | 15 | Add-Type -Path "$scriptFolder\Google.Apis.ChromeManagement.v1.dll" 16 | 17 | Add-Type -Path "$scriptFolder\Google.Apis.Auth.PlatformServices.dll" 18 | 19 | 20 | 21 | function Get-GoogleToken 22 | { 23 | #Set private key start/end tags 24 | $GooglePrivateKey = "-----BEGIN PRIVATE KEY-----\n$($GooglePrivateKey)\n-----END PRIVATE KEY-----\n" 25 | 26 | #Build json for authorization certificate 27 | $jsonFile = @{ } 28 | $jsonFile.Add("type", "service_account") 29 | $jsonFile.Add("project_id", $GoogleProjectID) 30 | $jsonFile.Add("private_key_id", $GooglePrivateID) 31 | $jsonFile.Add("private_key", $GooglePrivateKey) 32 | $jsonFile.Add("client_email", $GoogleClienteMail) 33 | $jsonFile.Add("client_id", $GoogleClientID) 34 | $jsonFile.Add("auth_uri", https://accounts.google.com/o/oauth2/auth) 35 | $jsonFile.Add("token_uri", https://oauth2.googleapis.com/token) 36 | $jsonFile.Add("auth_provider_x509_cert_url", https://www.googleapis.com/oauth2/v1/certs) 37 | $jsonFile.Add("client_x509_cert_url", https://www.googleapis.com/robot/v1/metadata/x509/$($GoogleClienteMail.Replace('@','%40'))) 38 | 39 | #Convert to json and fix 40 | $jsonCert = $jsonFile | ConvertTo-Json 41 | $jsonCert = $jsonCert.Replace(\\n, "\n") 42 | 43 | #Add necessary scopes 44 | $scopes = New-Object -TypeName System.Collections.Generic.List[string] 45 | $scopes.Add(https://www.googleapis.com/auth/admin.directory.device.chromebrowsers) 46 | 47 | #Create the credential and get token 48 | $googleCred = [Google.Apis.Auth.OAuth2.GoogleCredential]::FromJson($jsonCert) 49 | $googleCred = $googleCred.CreateScoped($scopes) 50 | $token = ([Google.Apis.Auth.OAuth2.ITokenAccess]$googleCred).GetAccessTokenForRequestAsync().GetAwaiter().GetResult() 51 | 52 | return $token 53 | } 54 | -------------------------------------------------------------------------------- /Windows/PowerShell/disableEdgeDefaultBrowserSettingsCampaigns.ps1: -------------------------------------------------------------------------------- 1 | 2 | #disable Edge default browser settings campaigns 3 | 4 | Invoke-Command -ScriptBlock { 5 | # policy doc - https://learn.microsoft.com/en-us/deployedge/microsoft-edge-policies#defaultbrowsersettingscampaignenabled 6 | #default browser settings campaigns policy 7 | $keyName = 'DefaultBrowserSettingsCampaignEnabled' 8 | $DefaultBrowserSettingsCampaignEnabledValue = 0 9 | 10 | #validate Microsoft policy path 11 | $MicrosoftRegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft' 12 | $test = test-path -path $MicrosoftRegistryPath 13 | 14 | #create if the required path doesn't exist 15 | if(-not($test)){ 16 | New-Item -Path $MicrosoftRegistryPath 17 | } 18 | 19 | #validate Microsoft\Edge policy path 20 | $MicrosoftEdgeRegistryPath = $MicrosoftRegistryPath + '\Edge' 21 | $test = test-path -path $MicrosoftEdgeRegistryPath 22 | 23 | #create if the required path doesn't exist 24 | if(-not($test)){ 25 | New-Item -Path $MicrosoftEdgeRegistryPath 26 | } 27 | 28 | $member = (Get-Item $MicrosoftEdgeRegistryPath).Property -contains $keyName 29 | 30 | if( $member ) { 31 | Set-ItemProperty -Path $MicrosoftEdgeRegistryPath -Name $keyName -Value $DefaultBrowserSettingsCampaignEnabledValue 32 | } 33 | else { 34 | New-ItemProperty -Path $MicrosoftEdgeRegistryPath -Name $keyName -PropertyType DWORD -Value $DefaultBrowserSettingsCampaignEnabledValue 35 | } 36 | 37 | #print enrollment token 38 | #Get-ItemProperty -Path $MicrosoftEdgeRegistryPath -Name $keyName 39 | } 40 | -------------------------------------------------------------------------------- /Windows/PowerShell/unenroll-admin-cmd-capture.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/Windows/PowerShell/unenroll-admin-cmd-capture.PNG -------------------------------------------------------------------------------- /Windows/README.md: -------------------------------------------------------------------------------- 1 | # Windows 2 | ## Pin Chrome to the taskbar 3 | You can pin Chrome to the Windows taskbar using the [XML configuration file](/Windows/PinChromeToTaskbar.xml). To learn more about task bar config file, deployment methods, and user experience, check out [Configure the applications pinned to the taskbar](https://learn.microsoft.com/en-us/windows/configuration/taskbar/pinned-apps?tabs=intune&pivots=windows-11). 4 | 5 | -------------------------------------------------------------------------------- /curl/authorization.md: -------------------------------------------------------------------------------- 1 | Create OAuth2.0 Client IDs and configure the OAuth concent screen. Refer to [Using OAuth 2.0 to Access Google APIs](https://developers.google.com/identity/protocols/oauth2). 2 | 3 | #### Get the Authorization code from the OAuth 2.0 Playground 4 | Navigate to the [OAuth 2.0 Playground](https://developers.google.com/oauthplayground/). Use the settings button to configure OAuth 2.0 configuration 5 | 6 | 7 | Add [scope to authorize](/../main/docs/auth.md). Click on "Exchnage authorization code for tokens" button found in Step 2. Don't forget to consent the request. You will need the resulting Authorization code, Refresh token, and Access token. 8 | 9 | Request using curl 10 | 11 | ``` 12 | curl -s --request POST --data "client_id=[CLIENT ID]&client_secret=[CLIENT SECRET]&refresh_token=[REFRESH TOKEN]&grant_type=refresh_token" https://accounts.google.com/o/oauth2/token 13 | ``` 14 | 15 | Response 16 | 17 | ```json 18 | { 19 | "access_token": "ya29.some_hash_value", 20 | "expires_in": 3599, 21 | "scope": "https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly", 22 | "token_type": "Bearer" 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/API_Get_Started.md: -------------------------------------------------------------------------------- 1 | # Getting started with CBCM API 2 | CBCM offers a wide range of APIs that let you integrate your services with CBCM. 3 | 4 | ## Learn about how authentication & authorization works in the CBCM API 5 | Authentication and authorization are used to verify identity and access to resources. This document identifies key terms you should know before implementing authentication and authorization in your app. 6 | 7 | ### OAuth consent process overview 8 | Use this credential to authenticate as an end user and requires your app to request and receive consent from the user (helpful in [Postman](https://github.com/google/ChromeBrowserEnterprise/tree/main/postman)). 9 | The following diagram shows the high-level steps of authentication and authorization for OAuth consent. 10 | 11 | 1. **Configure your Google Cloud project and app**: During development, you register your app in the Google Cloud console, defining authorization scopes and access credentials to authenticate your app. 12 | 13 | 2. **Authenticate your app for access**: The registered access credentials are evaluated when your app runs. A sign-in prompt might be displayed if your app authenticates as an end user. 14 | 15 | 3. **Request resources**: When your app needs access to Google resources, it asks Google to use the relevant scopes of access you previously registered. 16 | 17 | 4. **Ask for user consent**: If your app authenticates as an end user, Google displays the OAuth consent screen so the user can decide whether to grant your app access to the requested data. 18 | 19 | 5. **Send approved request for resources**: If the user consents to the scopes of access, your app bundles the credentials and the user-approved scopes of access into a request. The request is sent to the Google authorization server to obtain an access token. 20 | 21 | 6. **Google returns an access token**: The access token contains a list of granted scopes of access. If the returned list of scopes is more limited than the requested scopes of access, your app disables any features limited by the token. 22 | 23 | 7. **Access requested resources**: Your app uses the access token from Google to invoke the relevant APIs and access the resources. 24 | 25 | ### Service Account process overview 26 | Service accounts represent non-human users. They're intended for scenarios where a workload, such as a custom application, needs to access resources or perform actions without end-user involvement (beneficial for [CBCM-CSharp](https://github.com/google/ChromeBrowserEnterprise/tree/main/dotnet), [Python](https://github.com/google/ChromeBrowserEnterprise/tree/main/Python), and [PowerShell](https://github.com/google/ChromeBrowserEnterprise/tree/main/ps/src/cbcm) scripts). Authorization using a service account does **not** require consent from the user. 27 | 28 | Since you are creating [user-managed service accounts](https://cloud.google.com/iam/docs/service-accounts#user-managed-keys) in your project, **You are responsible for managing and securing these accounts**. See [Best practices for working with service accounts](https://cloud.google.com/iam/docs/best-practices-service-accounts). 29 | 30 | ## Follow these steps to set up the CBCM API 31 | 1. [Create a Google Cloud project](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/create_proj.MD) for your Google Workspace app, extension, or integration. 32 | 33 | 2. [Enable the APIs you want to use](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/proj_apis.MD) in your Google Cloud project. 34 | 35 | 3. Create a [service account](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/service_acct.MD). 36 | 37 | 4. Configure [OAuth consent](https://github.com/google/ChromeBrowserEnterprise/blob/main/postman/README.md) to ensure users can understand and approve what access your app has to their data. 38 | -------------------------------------------------------------------------------- /docs/App_Details_api.md: -------------------------------------------------------------------------------- 1 | # App Details API 2 | The [App Details API](https://developers.google.com/chrome/management/guides/app_details_api) enables you to get detailed information about requested or specified apps. The Reports API is part of the [Chrome Management API](https://developers.google.com/chrome/management/?hl=en_US). 3 | - Postman collection: [App Details API.postman_collection.json](https://github.com/google/ChromeBrowserEnterprise/blob/main/postman/App%20Details%20API.postman_collection.json) 4 | - Scope: https://www.googleapis.com/auth/chrome.management.appdetails.readonly 5 | 6 | ## Retrieve a specific app by its resource name 7 | Get a specific app for a customer by its resource name. If successful, the response body contains an instance of [AppDetails](https://developers.google.com/chrome/management/reference/rest/v1/customers.apps.android#AppDetails). 8 | #### Request 9 | ``` 10 | GET https://chromemanagement.googleapis.com/v1/customers/my_customer/apps/chrome/blipmdconlkpinefehnmjammfjpmpbjk 11 | ``` 12 | #### Response 13 | ``` 14 | { 15 | "name": "customers/C033fmrgf/apps/chrome/blipmdconlkpinefehnmjammfjpmpbjk", 16 | "displayName": "Lighthouse", 17 | "appId": "blipmdconlkpinefehnmjammfjpmpbjk", 18 | "revisionId": "100.0.0.0", 19 | "type": "CHROME", 20 | "iconUri": "https://lh3.googleusercontent.com/JsGtt7BHEbHhQl5OzJikROL49WGoN0fBNcU_mvLRjWqx7nm7r7rzdG0DpET4qcK1FhNkFpcKf600G-Eoxx-_q3D4iA", 21 | "detailUri": "https://chrome.google.com/webstore/detail/blipmdconlkpinefehnmjammfjpmpbjk", 22 | "firstPublishTime": "2016-03-20T00:58:48.378Z", 23 | "latestPublishTime": "2019-11-21T03:56:08.202Z", 24 | "publisher": "developers.google.com/web", 25 | "homepageUri": "https://developers.google.com/web/tools/lighthouse/", 26 | "reviewNumber": "286", 27 | "reviewRating": 4.4, 28 | "chromeAppInfo": { 29 | "supportEnabled": false, 30 | "minUserCount": 800000, 31 | "permissions": [ 32 | { 33 | "type": "activetab", 34 | "documentationUri": "https://developer.chrome.com/docs/extensions/mv3/manifest/activeTab/", 35 | "accessUserData": true 36 | }, 37 | { 38 | "type": "storage", 39 | "documentationUri": "https://developer.chrome.com/docs/extensions/reference/storage/", 40 | "accessUserData": false 41 | } 42 | ], 43 | "isTheme": false, 44 | "googleOwned": false, 45 | "isCwsHosted": true, 46 | "kioskEnabled": false, 47 | "isKioskOnly": false, 48 | "type": "EXTENSION", 49 | "isExtensionPolicySupported": false 50 | } 51 | } 52 | ``` 53 | 54 | ## Retrieve Extension Workflow Request Count 55 | Generate summary of [app installation requests](https://developers.google.com/chrome/management/reference/rest/v1/customers.apps/countChromeAppRequests). 56 | #### Request 57 | ``` 58 | GET https://chromemanagement.googleapis.com/v1/customers/my_customer/apps:countChromeAppRequests?orgUnitId=&pageSize=1&orderBy=latestRequestTime desc 59 | ``` 60 | #### Response 61 | ``` 62 | { 63 | "requestedApps": [ 64 | { 65 | "appId": "hkgfoiooedgoejojocmhlaklaeopbecg", 66 | "displayName": "Picture-in-Picture Extension (by Google)", 67 | "appDetails": "customers/C033fmrgf/apps/chrome/hkgfoiooedgoejojocmhlaklaeopbecg", 68 | "iconUri": "https://lh3.googleusercontent.com/cvfpnTKw3B67DtM1ZpJG2PNAIjP6hVMOyYy403X4FMkOuStgG1y4cjCn21vmTnnsip1dTZSVsWBA9IxutGuA3dVDWhg", 69 | "detailUri": "https://chrome.google.com/webstore/detail/hkgfoiooedgoejojocmhlaklaeopbecg", 70 | "requestCount": "1", 71 | "latestRequestTime": "2022-07-29T13:15:23.423Z" 72 | } 73 | ], 74 | "nextPageToken": "AGwWS9CHvU_3ge1dP_ewstOVAA8ZDbLoFeCCGcpv3CJ1Dbh-06wgGPvWYaW5cD84fs5bcvo48e0sEXdpVI8=", 75 | "totalSize": 19 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /docs/Chrome_Management_Reports_api.md: -------------------------------------------------------------------------------- 1 | # Chrome Management API 2 | The [Chrome Management API](https://developers.google.com/chrome/management/reference/rest) enables you to generate reports that give you aggregate information on your managed Chrome Browser deployment. 3 | - Postman collections: 4 | [Chrome Management - Apps API](https://www.postman.com/google-chrome-enterprise-apis/workspace/google-chrome-enterprise-public/collection/17723612-1f198842-802b-4900-af38-7ffc1f32bfdf) 5 | [Chrome Management - Reports API](https://www.postman.com/google-chrome-enterprise-apis/workspace/google-chrome-enterprise-public/collection/17723612-cae3a18e-7399-4e9f-83b2-084b8798ffed) 6 | - Scope: https://www.googleapis.com/auth/chrome.management.reports.readonly 7 | 8 | ## Chrome Management Apps API 9 | 10 | ### Retrieve a specific app by its resource name 11 | [customers.apps.chrome.get](https://developers.google.com/chrome/management/reference/rest/v1/customers.apps.chrome/get) 12 | 13 | ### Retrieve Extension Workflow Requests 14 | [countChromeAppRequests](https://developers.google.com/chrome/management/reference/rest/v1/customers.apps/countChromeAppRequests) 15 | 16 | ## Retrieve a list of devices that have requested to install an extension 17 | [fetchDevicesRequestingExtension](https://developers.google.com/chrome/management/reference/rest/v1/customers.apps/fetchDevicesRequestingExtension) 18 | 19 | ### Retrieve a list of users that have requested to install an extension 20 | [fetchUsersRequestingExtension](https://developers.google.com/chrome/management/reference/rest/v1/customers.apps/fetchUsersRequestingExtension) 21 | 22 | ## Chrome Management Reports API 23 | 24 | ### Chrome Browsers Needing Attention 25 | [countChromeBrowsersNeedingAttention](https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countChromeBrowsersNeedingAttention) 26 | 27 | ### Get a count of Chrome crash events 28 | [countChromeCrashEvents](https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countChromeCrashEvents) 29 | 30 | ### Generate report of all installed Chrome versions 31 | [countChromeVersions](https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countChromeVersions) 32 | 33 | ### Generate report of app installations 34 | [countInstalledApps](https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countInstalledApps) 35 | 36 | ### Generate report to find devices that have an app installed 37 | [findInstalledAppDevices ](https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/findInstalledAppDevices) 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /docs/Directory_api.md: -------------------------------------------------------------------------------- 1 | # Directory API 2 | The [Directory API](https://developers.google.com/admin-sdk/directory) is used to create and manage resources attached to your Google domain, such as users, org charts, and groups. 3 | - Postman collection: [Directory API.postman_collection.json](https://github.com/google/ChromeBrowserEnterprise/blob/main/postman/Directory%20API.postman_collection.json) 4 | - Scope: https://www.googleapis.com/auth/admin.directory.orgunit 5 | 6 | ## Retrieves all organizational units 7 | Retrieves a [list](https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits/list) of all organizational units for an account. 8 | #### Request 9 | ``` 10 | GET https://www.googleapis.com/admin/directory/v1/customer/my_customer/orgunits?type=ALL&maxResults=1&pageToken 11 | ``` 12 | #### Response 13 | ``` 14 | { 15 | "kind": "admin#directory#orgUnits", 16 | "etag": "\"7dD2lEGw_cSWElgnmooDH6C54E0q2uifMqS1m-4dUqU/7fLPaFivzUt-IwJ16r-To7s2daU\"", 17 | "organizationUnits": [ 18 | { 19 | "kind": "admin#directory#orgUnit", 20 | "etag": "\"7dD2lEGw_cSWElgnmooDH6C54E0q2uifMqS1m-4dUqU/mzVAzGt4X7LTuMjT4MDeg-x-Dl0\"", 21 | "name": "Seattle", 22 | "description": "Seattle Office", 23 | "orgUnitPath": "/North America/Seattle", 24 | "orgUnitId": "id:03ph8a2z496ipdk", 25 | "parentOrgUnitPath": "/North America", 26 | "parentOrgUnitId": "id:03ph8a2z1v3xa3o" 27 | }, 28 | { 29 | "kind": "admin#directory#orgUnit", 30 | "etag": "\"7dD2lEGw_cSWElgnmooDH6C54E0q2uifMqS1m-4dUqU/jU8l7HvmxKEYE1tPO6852LN52WI\"", 31 | "name": "Sydney", 32 | "description": "Sydney Office", 33 | "orgUnitPath": "/APAC/Sydney", 34 | "orgUnitId": "id:03ph8a2z2awn3mc", 35 | "parentOrgUnitPath": "/APAC", 36 | "parentOrgUnitId": "id:03ph8a2z0vl7zj4" 37 | }, 38 | ... 39 | ] 40 | } 41 | ``` 42 | 43 | ## Retrieve an organizational unit 44 | Retrieves [an organizational unit](https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits/get). 45 | #### Request 46 | ``` 47 | GET https://www.googleapis.com/admin/directory/v1/customer/my_customer/orgunits/North America/Austin 48 | ``` 49 | #### Response 50 | ``` 51 | { 52 | "kind": "admin#directory#orgUnit", 53 | "etag": "\"7dD2lEGw_cSWElgnmooDH6C54E0q2uifMqS1m-4dUqU/oGdJG7Et1xmNUR5VdTTYF5MjflM\"", 54 | "name": "Austin", 55 | "description": "Austin Office", 56 | "orgUnitPath": "/North America/Austin", 57 | "orgUnitId": "id:03ph8a2z4jbpnn4", 58 | "parentOrgUnitPath": "/North America", 59 | "parentOrgUnitId": "id:03ph8a2z1v3xa3o" 60 | } 61 | ``` 62 | 63 | ## Retrieve all child organizational units 64 | 65 | #### Request 66 | ``` 67 | GET https://www.googleapis.com/admin/directory/v1/customer/my_customer/orgunits/?orgUnitPath=North America&type=all 68 | ``` 69 | #### Response 70 | ``` 71 | { 72 | "kind": "admin#directory#orgUnits", 73 | "etag": "\"7dD2lEGw_cSWElgnmooDH6C54E0q2uifMqS1m-4dUqU/WUDXpc9TJxyJ3Qap_CccFJsCz8k\"", 74 | "organizationUnits": [ 75 | { 76 | "kind": "admin#directory#orgUnit", 77 | "etag": "\"7dD2lEGw_cSWElgnmooDH6C54E0q2uifMqS1m-4dUqU/mzVAzGt4X7LTuMjT4MDeg-x-Dl0\"", 78 | "name": "Seattle", 79 | "description": "Seattle Office", 80 | "orgUnitPath": "/North America/Seattle", 81 | "orgUnitId": "id:03ph8a2z496ipdk", 82 | "parentOrgUnitPath": "/North America", 83 | "parentOrgUnitId": "id:03ph8a2z1v3xa3o" 84 | }, 85 | { 86 | "kind": "admin#directory#orgUnit", 87 | "etag": "\"7dD2lEGw_cSWElgnmooDH6C54E0q2uifMqS1m-4dUqU/h2j9vXveK_uWIphIPmBwj8fRXNY\"", 88 | "name": "New York", 89 | "description": "New York Office", 90 | "orgUnitPath": "/North America/New York", 91 | "orgUnitId": "id:03ph8a2z1604z3y", 92 | "parentOrgUnitPath": "/North America", 93 | "parentOrgUnitId": "id:03ph8a2z1v3xa3o" 94 | }, 95 | ... 96 | ] 97 | } 98 | ``` 99 | 100 | ## Delete an organizational unit 101 | [Removes](https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits/delete) an organizational unit. 102 | #### Request 103 | ``` 104 | curl --location --request DELETE 'https://www.googleapis.com/admin/directory/v1/customer/my_customer/orgunits/UX/Research/Research_support' \ 105 | --header 'Authorization: Bearer ' 106 | ``` 107 | #### Response 108 | ``` 109 | 110 | ``` 111 | 112 | ## Update an organizational unit 113 | [Updates](https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits/update) an organizational unit. 114 | #### Request 115 | ``` 116 | curl --location --request PUT 'https://www.googleapis.com/admin/directory/v1/customer/my_customer/orgunits/UX/Research/Research_support' \ 117 | --header 'Authorization: Bearer ' \ 118 | --header 'Content-Type: application/json' \ 119 | --data-raw '{ 120 | "description": "Where is Algonquin" 121 | }' 122 | ``` 123 | #### Response 124 | ``` 125 | 126 | ``` 127 | 128 | ## Create an organizational unit 129 | [Adds](https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits/insert) an organizational unit. 130 | #### Request 131 | ``` 132 | curl --location --request POST 'https://admin.googleapis.com/admin/directory/v1/customer/my_customer/orgunits' \ 133 | --header 'Authorization: Bearer ' \ 134 | --header 'Content-Type: application/json' \ 135 | --data-raw '{ 136 | "name": "Research_support", 137 | "description": "The research support team", 138 | "parentOrgUnitPath": "/UX/Research", 139 | "blockInheritance": false 140 | }' 141 | ``` 142 | #### Response 143 | ``` 144 | 145 | ``` 146 | -------------------------------------------------------------------------------- /docs/Enrollment_Token_api.md: -------------------------------------------------------------------------------- 1 | # Enrollment Token API 2 | The [Enrollment Token API](https://developers.google.com/admin-sdk/reports/v1/get-start/overview) is a RESTful API you can use to access information about the Chrome browser enrollment token. 3 | - Postman collection: [Enrollment Token API.postman_collection.json](https://github.com/google/ChromeBrowserEnterprise/blob/main/postman/Enrollment%20Token%20API.postman_collection.json) 4 | - Scope: https://www.googleapis.com/auth/admin.directory.device.chromebrowsers 5 | 6 | ## List all enrollment tokens for an account 7 | To retrieve a report of all administrative activities done for an account, use the following GET HTTP request and include the authorization token. 8 | #### Request 9 | ``` 10 | GET https://www.googleapis.com/admin/directory/v1.1beta1/customer/my_customer/chrome/enrollmentTokens?orgUnitPath=&pageToken&pageSize=100&query 11 | ``` 12 | #### Response 13 | ``` 14 | { 15 | "kind": "admin#directory#chromeEnrollmentTokens", 16 | "chromeEnrollmentTokens": [ 17 | { 18 | "tokenPermanentId": "50a2573a-923c-4eac-b7f9-49a78e346684", 19 | "kind": "admin#directory#chromeEnrollmentToken", 20 | "token": "9e4e1468-e978-494e-9dd7-531b83ba1bee", 21 | "customerId": "033fmrgf", 22 | "orgUnitPath": "/AlexTest/FictionalCo", 23 | "state": "active", 24 | "createTime": "2022-08-23T14:08:38Z", 25 | "creatorId": "108572335719235898846", 26 | "tokenType": "chromeBrowser" 27 | }, 28 | { 29 | "tokenPermanentId": "dc0087b9-8d32-46ff-bf9a-3d0966ead680", 30 | "kind": "admin#directory#chromeEnrollmentToken", 31 | "token": "ed61a74f-9040-458e-b799-4e4ac9120aef", 32 | "customerId": "033fmrgf", 33 | "orgUnitPath": "/AlexTest/FictionalCo/Test", 34 | "state": "active", 35 | "createTime": "2022-08-15T17:37:46Z", 36 | "creatorId": "108572335719235898846", 37 | "tokenType": "chromeBrowser" 38 | }, 39 | ... 40 | ] 41 | } 42 | ``` 43 | 44 | ## List all enrollment tokens for an account 45 | To retrieve a report of all administrative activities done for an account, use the following GET HTTP request and include the authorization token. 46 | #### Request 47 | ``` 48 | GET https://www.googleapis.com/admin/directory/v1.1beta1/customer/my_customer/chrome/enrollmentTokens?orgUnitPath=&pageToken&pageSize=100&query 49 | ``` 50 | #### Response 51 | ``` 52 | { 53 | "kind": "admin#directory#chromeEnrollmentTokens", 54 | "chromeEnrollmentTokens": [ 55 | { 56 | "tokenPermanentId": "50a2573a-923c-4eac-b7f9-49a78e346684", 57 | "kind": "admin#directory#chromeEnrollmentToken", 58 | "token": "9e4e1468-e978-494e-9dd7-531b83ba1bee", 59 | "customerId": "033fmrgf", 60 | "orgUnitPath": "/AlexTest/FictionalCo", 61 | "state": "active", 62 | "createTime": "2022-08-23T14:08:38Z", 63 | "creatorId": "108572335719235898846", 64 | "tokenType": "chromeBrowser" 65 | }, 66 | { 67 | "tokenPermanentId": "dc0087b9-8d32-46ff-bf9a-3d0966ead680", 68 | "kind": "admin#directory#chromeEnrollmentToken", 69 | "token": "ed61a74f-9040-458e-b799-4e4ac9120aef", 70 | "customerId": "033fmrgf", 71 | "orgUnitPath": "/AlexTest/FictionalCo/Test", 72 | "state": "active", 73 | "createTime": "2022-08-15T17:37:46Z", 74 | "creatorId": "108572335719235898846", 75 | "tokenType": "chromeBrowser" 76 | }, 77 | ... 78 | ] 79 | } 80 | ``` 81 | 82 | ## Create an enrollment token 83 | 84 | #### Request 85 | ``` 86 | curl --location --request POST 'https://www.googleapis.com/admin/directory/v1.1beta1/customer/my_customer/chrome/enrollmentTokens' \ 87 | --header 'Authorization: Bearer ' \ 88 | --header 'Content-Type: application/json' \ 89 | --data-raw '{ 90 | "token_type": "CHROME_BROWSER", 91 | "org_unit_path": "/UX/Research/Research_support" 92 | }' 93 | ``` 94 | #### Response 95 | ``` 96 | { 97 | "tokenPermanentId": "77dc2a5a-ebec-44c1-bcee-84c09bb7312e", 98 | "kind": "admin#directory#chromeEnrollmentToken", 99 | "token": "33d20f0f-4d1e-4fa3-a39a-105e4b01c41b", 100 | "customerId": "033fmrgf", 101 | "orgUnitPath": "/UX/Research/Research_support", 102 | "state": "active", 103 | "createTime": "2022-09-18T21:08:18Z", 104 | "creatorId": "113456549147281770764", 105 | "tokenType": "chromeBrowser" 106 | } 107 | ``` 108 | 109 | ## Revoke an enrollment token 110 | To revoke an enrollment token, use the following POST request and include the token Permanent Id 111 | #### Request 112 | ``` 113 | curl --location --request POST 'https://www.googleapis.com/admin/directory/v1.1beta1/customer/my_customer/chrome/enrollmentTokens/77dc2a5a-ebec-44c1-bcee-84c09bb7312e:revoke' \ 114 | --header 'Authorization: Bearer ' 115 | ``` 116 | #### Response 117 | ``` 118 | 119 | ``` 120 | 121 | -------------------------------------------------------------------------------- /docs/ExtensionRiskSignals_FromImport.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/docs/ExtensionRiskSignals_FromImport.PNG -------------------------------------------------------------------------------- /docs/ExtensionRiskSignals_FromOU.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/docs/ExtensionRiskSignals_FromOU.PNG -------------------------------------------------------------------------------- /docs/auth.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Scopes 4 | |Scope |Description | 5 | |-------------------------------|-----------------------------| 6 | | `https://www.googleapis.com/auth/admin.directory.device.chromebrowsers.readonly`|Chrome Browser Cloud Managment (CBCM) - get detailed information on enrolled browsers and enrollment tokens (read-only)| 7 | | `https://www.googleapis.com/auth/admin.directory.device.chromebrowsers`|Chrome Browser Cloud Managment (CBCM) - lets you view and modify enrolled browsers and enrollment tokens| 8 | | `https://www.googleapis.com/auth/chrome.management.reports.readonly`|Reports - Chrome versions and installed apps | 9 | | `https://www.googleapis.com/auth/chrome.management.appdetails.readonly`|App Details- get detailed information about requested or specified apps | 10 | | `https://www.googleapis.com/auth/chrome.management.policy.readonly`|Chrome Policy - lets you view Chrome policies for devices and users | 11 | | `https://www.googleapis.com/auth/chrome.management.policy`|Chrome Policy - lets you view and modify Chrome policies for devices and users | 12 | | `https://www.googleapis.com/auth/admin.directory.orgunit.readonly`|Org Units - lets you view organizational units | 13 | | `https://www.googleapis.com/auth/admin.directory.orgunit`|Org Units - lets you view and modify organizational units | 14 | | `https://www.googleapis.com/auth/admin.reports.audit.readonly`|Admin Console Reports - lets you view activities done by administrators using the Admin console and oAuth token acivities | 15 | -------------------------------------------------------------------------------- /docs/create_proj.MD: -------------------------------------------------------------------------------- 1 | # Create a Google Cloud project 2 | A Google Cloud project is required to use CBCM APIs. This project forms the basis for creating, enabling, and using all Google Cloud services, including managing APIs. 3 | 4 | To create a Google Cloud project: 5 | 6 | 1. In the Google Cloud console, go to **Menu > IAM & Admin > Create a Project**. 7 | 8 | > Go to [Create a Project](https://console.cloud.google.com/projectcreate) 9 | 10 | 2. In the **Project Name** field, enter a descriptive name for your project. 11 | Optional: To edit the **Project ID**, click **Edit**. The project ID can't be changed after the project is created, so choose an ID that meets your needs for the lifetime of the project. 12 | 13 | 3. In the **Location** field, click **Browse** to display potential locations for your project. Then, click Select. 14 | 15 | 4. Click **Create**. The console navigates to the Dashboard page, and your project is created within a few minutes. 16 | For further information on Google Cloud projects, refer to [Creating and managing projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects). 17 | 18 | ## Next step 19 | [Enable Google CBCM APIs](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/proj_apis.MD) 20 | -------------------------------------------------------------------------------- /docs/create_project.md: -------------------------------------------------------------------------------- 1 | # Creating and managing projects 2 | ## Creating a project 3 | To create a project, you must have the resourcemanager.projects.create permission. This permission is included in roles like the Project Creator role (roles/resourcemanager.projectCreator). 4 | 5 | To create a new project, do the following: 6 | 7 | 1. Go to the **[Manage resources](https://console.cloud.google.com/cloud-resource-manager)** page in the Google Cloud console. 8 | 2. On the **Select organization** drop-down list at the top of the page, select the organization resource in which you want to create a project. 9 | 3. Click **Create** Project 10 | 4. In the New Project window that appears, enter a project name. A project name can contain only letters, numbers, single quotes, hyphens, spaces, or exclamation points, and must be between 4 and 30 characters. 11 | 5. Enter the parent organization or folder resource in the **Location** box. That resource will be the hierarchical parent of the new project. If No organization is the only option, you will need to reach out to your company Cloud admin. 12 | 6. When you're finished entering new project details, click **Create**. 13 | 14 | ## Get an existing project 15 | You can get an existing project using the Google Cloud console. If you are not a project owner, you must have the permissions included in the Browser role (roles/browser). 16 | 17 | To view a project using the Google Cloud console, do the following: 18 | 1. Go to the **[Dashboard page](https://console.cloud.google.com/home?_ga=2.56387567.536968724.1673197321-1348019484.1672850961)** in the Google Cloud console. 19 | 2. Click the Select from drop-down list at the top of the page. In the Select from window that appears, select your project. 20 | 21 | ## Shutting down (deleting) projects 22 | You can shut down projects using the Google Cloud console. [Refer to this article](https://cloud.google.com/resource-manager/docs/creating-managing-projects) for additional information. 23 | 24 | ## Restoring a project 25 | Project owners can restore a deleted project within the 30-day recovery period that starts when the project is shut down. [Refer to this article](https://cloud.google.com/resource-manager/docs/creating-managing-projects#restoring_a_project) for additional information. 26 | -------------------------------------------------------------------------------- /docs/images/blank.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/images/consent_screen_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/docs/images/consent_screen_1.png -------------------------------------------------------------------------------- /docs/images/consent_screen_scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/docs/images/consent_screen_scope.png -------------------------------------------------------------------------------- /docs/images/oAuth_Cred_Create.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ChromeBrowserEnterprise/5bd9bab4bac21180209a84e67ee5cc67bd6fcaf9/docs/images/oAuth_Cred_Create.PNG -------------------------------------------------------------------------------- /docs/policy_examples/com.google.Chrome.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HomepageLocation 6 | https://www.google.com 7 | HomepageIsNewTabPage 8 | 9 | DefaultBrowserSettingEnabled 10 | 11 | RestoreOnStartup 12 | 1 13 | ManagedBookmarks 14 | 15 | 16 | toplevel_name 17 | Managed bookmarks folder 18 | 19 | 20 | name 21 | Google 22 | url 23 | google.com 24 | 25 | 26 | name 27 | Youtube 28 | url 29 | youtube.com 30 | 31 | 32 | children 33 | 34 | 35 | name 36 | Chromium 37 | url 38 | chromium.org 39 | 40 | 41 | name 42 | Chromium Developers 43 | url 44 | dev.chromium.org 45 | 46 | 47 | name 48 | Chrome links 49 | 50 | 51 | MaxConnectionsPerProxy 52 | 99 53 | SafeBrowsingProtectionLevel 54 | 1 55 | ExtensionInstallForcelist 56 | 57 | noondiphcddnnabmjcihcjfbhfklnnep 58 | djflhoibgkdhkhhcedjiklpkjnoahfmg 59 | 60 | MetricsReportingEnabled 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/policy_examples/initial_preferences: -------------------------------------------------------------------------------- 1 | { 2 | "distribution": { 3 | "import_bookmarks_from_file": "bookmarks.html", 4 | "do_not_create_desktop_shortcut": true, 5 | "do_not_create_quick_launch_shortcut": true, 6 | "system_level": true, 7 | "verbose_logging": true 8 | }, 9 | "first_run_tabs": [ 10 | "http://www.example.com", 11 | "http://welcome_page", 12 | "http://new_tab_page" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /docs/policy_examples/managed_policies.json: -------------------------------------------------------------------------------- 1 | { 2 | "HomepageLocation": "https://www.google.com", 3 | "HomepageIsNewTabPage": false, 4 | "DefaultBrowserSettingEnabled": true, 5 | "RestoreOnStartup": 1, 6 | "SafeBrowsingProtectionLevel": 1, 7 | "MaxConnectionsPerProxy": 99, 8 | "ExtensionInstallForcelist": [ 9 | "noondiphcddnnabmjcihcjfbhfklnnep", 10 | "djflhoibgkdhkhhcedjiklpkjnoahfmg" 11 | ], 12 | "ManagedBookmarks": [ 13 | { 14 | "toplevel_name": "My managed bookmarks folder" 15 | }, 16 | { 17 | "name": "Google", 18 | "url": "google.com" 19 | }, 20 | { 21 | "name": "Youtube", 22 | "url": "youtube.com" 23 | }, 24 | { 25 | "children": [ 26 | { 27 | "name": "Chromium", 28 | "url": "chromium.org" 29 | }, 30 | { 31 | "name": "Chromium Developers", 32 | "url": "dev.chromium.org" 33 | } 34 | ], 35 | "name": "Chrome links" 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /docs/policy_examples/policies.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | ; chrome version: 112.0.5615.138 3 | 4 | [HKEY_LOCAL_MACHINE\Software\Policies\Google\Chrome] 5 | "HomepageLocation"="https://www.google.com" 6 | "HomepageIsNewTabPage"=dword:00000001 7 | "RestoreOnStartup"=dword:00000001 8 | "SafeBrowsingProtectionLevel"=dword:00000001 9 | "MaxConnectionsPerProxy"=dword:00000099 10 | "ManagedBookmarks"="[{\"toplevel_name\": \"Managedbookmarksfolder\"},{\"name\": \"Google\",\"url\": \"google.com\"},{\"name\": \"Youtube\",\"url\": \"youtube.com\"},{\"children\": [{\"name\": \"Chromium\",\"url\": \"chromium.org\"},{\"name\": \"ChromiumDevelopers\",\"url\": \"dev.chromium.org\"}],\"name\": \"Chromelinks\"}]" 11 | 12 | 13 | [HKEY_LOCAL_MACHINE\Software\Policies\Google\Chrome\ExtensionInstallForcelist] 14 | "1"="noondiphcddnnabmjcihcjfbhfklnnep" 15 | "2"="djflhoibgkdhkhhcedjiklpkjnoahfmg" 16 | 17 | 18 | [HKEY_LOCAL_MACHINE\Software\Policies\Google\Chrome\Recommended] 19 | "MetricsReportingEnabled"=dword:00000001 20 | -------------------------------------------------------------------------------- /docs/policy_examples/recommended_policies.json: -------------------------------------------------------------------------------- 1 | { 2 | "MetricsReportingEnabled": true 3 | } 4 | -------------------------------------------------------------------------------- /docs/proj_apis.MD: -------------------------------------------------------------------------------- 1 | # Enable Google CBCM APIs 2 | Before using Google APIs, you need to turn them on in a Google Cloud project. You can turn on one or more APIs in a single Google Cloud project. APIs you need to enable: 3 | * Admin SDK API 4 | * Chrome Management API 5 | * Chrome Policy API 6 | 7 | To enable an API in your Cloud project: 8 | 9 | 1. In the Google Cloud console, go to **Menu > API/Service Details**. 10 | > Go to [Product Library](https://console.cloud.google.com/apis/dashboard?project=) 11 | 12 | 2. Click the API that you want to turn on. 13 | 3. Click **Enable**. 14 | 4. To enable more APIs, repeat these steps. 15 | 16 | ## Next step 17 | Configure the [Service account](https://github.com/google/ChromeBrowserEnterprise/blob/main/docs/service_acct.MD) for automated services that runs as a process - [CBCM-CSharp](https://github.com/google/ChromeBrowserEnterprise/tree/main/dotnet), [Python](https://github.com/google/ChromeBrowserEnterprise/tree/main/Python), and [PowerShell](https://github.com/google/ChromeBrowserEnterprise/tree/main/ps/src/cbcm) scripts. 18 | -------------------------------------------------------------------------------- /docs/service_acct.MD: -------------------------------------------------------------------------------- 1 | # Service account 2 | A Service account is a credential used for server-to-server interactions, such as a faceless app that runs as a process to access some data or perform some operation. 3 | 4 | ## Create a service account 5 | 1. In the Google Cloud console, go to Menu > **IAM & Admin > Service Accounts**. 6 | 2. Click **Create service account**. 7 | 3. Fill in the service account details, then click **Create and continue**. Note: By default, Google creates a unique service account ID. If you want to change the ID, modify the ID in the service account ID field. 8 | 4. You do not have to assign roles (skip it). 9 | 5. Click **Continue**. 10 | 6. You do not have to grant users access to this service account (skip it). 11 | 7. Click **Done**. 12 | 13 | ## Create credentials for a service account 14 | You need to obtain credentials in the form of a public/private key pair. Your code uses these credentials to authorize service account actions within your app. 15 | To obtain credentials for your service account: 16 | 1. In the Google Cloud console, go to Menu > **IAM & Admin > Service Accounts**. 17 | 2. Select your service account. 18 | 3. Click **Keys > Add key > Create new key**. 19 | 4. Select **JSON**, then click **Create**. Your new public/private key pair is generated and downloaded to your machine as a new file. This file is the only copy of this key. For information about how to store your key securely, see [Managing service account keys](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys). 20 | 5. Click **Close**. 21 | 22 | ## Grant access to a service account 23 | To call APIs, your service account needs to be granted special privileges in the Google Admin Console by a super administrator account. 24 | 25 | ### Create the Chrome Browser custom role 26 | 1. In the Google Admin console, go to Menu > **Account > Admin roles**. 27 | 2. Click **Create new role**. 28 | 3. Fill in the Role info details, then click **Continue**. 29 | 4. In **Select Privileges**, enable these Admin console privileges. 30 | 31 | **Organizational Units**. 32 | 33 | Note: This will automatically enable Admin API privileges for Organization Units, and you want to leave that in the enabled state. 34 | - [x] Read 35 | - [x] Create 36 | - [x] Update 37 | - [x] Delete 38 | 39 | **Services > Chrome Management** 40 | - [x] Manage User Settings 41 | - [x] Managed Browsers 42 | - [x] View Reports 43 | 44 | 5. Click **Create Role** 45 | 46 | ### Assign service account to the Chrome Browser custom role 47 | 1. Select the Chrome Browser custom role. 48 | 2. Click on **Assign role** in the **Admins** card. 49 | 3. Click on **Assign service accounts**. 50 | 4. Find your service account's "**client_email**" and copy the value to your clipboard. This data is found in the Credential JSON file you downloaded from earlier steps. 51 | 5. Paste the client email into the Add service account and click **Add**. 52 | 6. Click **Assign Role**. 53 | 54 | ## Next step 55 | Configure [OAuth consent screen and client Id for Postman](https://github.com/google/ChromeBrowserEnterprise/blob/main/postman/README.md) 56 | -------------------------------------------------------------------------------- /docs/start.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | You can use the Postman collections to interact with Google APIs like Chrome Browser Cloud Management, Chrome Browser Enrollment Token API, Chrome Policy, and Extensions. 3 | 4 | ## Setup 5 | 6 | ### Create a Google project 7 | Go to the [Google API Console](https://console.developers.google.com/project). Sign-in using the same Google Account that you use for the admin console. Click Create project, enter a name, and click Create. 8 | 9 | ### Enable Google APIs 10 | Next, we need to enable the following Google APIs in your project. 11 | * [Admin SDK API](https://console.developers.google.com/apis/api/admin.googleapis.com/overview?project=_) 12 | * [Chrome Management API](https://console.developers.google.com/apis/api/chromemanagement.googleapis.com/overview?project=_) 13 | * [Chrome Policy API](https://console.developers.google.com/apis/api/chromepolicy.googleapis.com/overview?project=_) 14 | 15 | To enable an API for your project, do the following: 16 | 17 | 1. Open the [API Library](https://console.developers.google.com/apis/library) in the Google API Console. If prompted, select a project or create a new one. The API Library lists all available APIs, grouped by product family and popularity. 18 | 2. If the API you want to enable isn't visible in the list, use search to find it by name (described above). 19 | 3. Select the API you want to enable, then click the Enable button. 20 | 4. If prompted, accept the API's Terms of Service. 21 | 22 | ### Postman 23 | You can use the latest Postman [on the web](https://identity.getpostman.com/signup?continue=https%3A%2F%2Fgo.postman.co%2Fbuild&_ga=2.39310499.1216381035.1635882050-1482705519.1632930853) or [desktop app](https://www.postman.com/downloads/) to [import the collections](https://learning.postman.com/docs/getting-started/importing-and-exporting-data/). 24 | 25 | ## Next > [Authorization](auth.md) 26 | 27 | -------------------------------------------------------------------------------- /mobile/ChromeBrowserCloudManagement.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadDescription 6 | Cloud Management enrollment for the Google Chrome web browser 7 | PayloadDisplayName 8 | Chrome Browser Cloud Management 9 | PayloadIdentifier 10 | io.kandji.chrome.FDB0E555-2C6E-49AE-B117-AF62C787444C 11 | PayloadOrganization 12 | Kandji, Inc. 13 | PayloadScope 14 | System 15 | PayloadType 16 | Configuration 17 | PayloadUUID 18 | FDB0E555-2C6E-49AE-B117-AF62C787444C 19 | PayloadVersion 20 | 1 21 | PayloadContent 22 | 23 | 24 | CloudManagementEnrollmentToken 25 | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 26 | CloudManagementEnrollmentMandatory 27 | 28 | PayloadEnabled 29 | 30 | PayloadDisplayName 31 | Chrome Browser Settings 32 | PayloadIdentifier 33 | com.google.Chrome.4F720473-6832-4CE0-A895-E9C3FC6F8CBD 34 | PayloadUUID 35 | 4F720473-6832-4CE0-A895-E9C3FC6F8CBD 36 | PayloadType 37 | com.google.Chrome 38 | PayloadVersion 39 | 1 40 | 41 | 42 | 43 | 44 | --------------------------------------------------------------------------------