diff --git a/Makefile.in b/Makefile.in index 10cc4a2c..0789e183 100644 --- a/Makefile.in +++ b/Makefile.in @@ -55,7 +55,7 @@ endif system_unit_files = contrib/systemd/onedrive@.service user_unit_files = contrib/systemd/onedrive.service -DOCFILES = README.md config LICENSE CHANGELOG.md docs/Docker.md docs/INSTALL.md docs/SharePoint-Shared-Libraries.md docs/USAGE.md docs/BusinessSharedFolders.md docs/advanced-usage.md +DOCFILES = README.md config LICENSE CHANGELOG.md docs/Docker.md docs/INSTALL.md docs/SharePoint-Shared-Libraries.md docs/USAGE.md docs/BusinessSharedFolders.md docs/advanced-usage.md docs/application-security.md ifneq ("$(wildcard /etc/redhat-release)","") RHEL = $(shell cat /etc/redhat-release | grep -E "(Red Hat Enterprise Linux Server|CentOS)" | wc -l) diff --git a/config b/config index e8e365c6..18f7a677 100644 --- a/config +++ b/config @@ -51,4 +51,5 @@ # webhook_expiration_interval = "86400" # webhook_renewal_interval = "43200" # space_reservation = "50" -# display_running_config = "false" \ No newline at end of file +# display_running_config = "false" +# read_only_auth_scope = "false" diff --git a/docs/application-security.md b/docs/application-security.md new file mode 100644 index 00000000..45ef27ae --- /dev/null +++ b/docs/application-security.md @@ -0,0 +1,67 @@ +# OneDrive Client for Linux Application Security +This document details the application security used, and provides details for users on changing these security options. + +There are 2 main components regarding security for this application: +* Azure Application Permissions +* User Authentication Permissions + +## Default Application Security +Security options should follow the security principal of 'least privilege': +> The principle that a security architecture should be designed so that each entity +> is granted the minimum system resources and authorizations that the entity needs +> to perform its function. + +Reference: [https://csrc.nist.gov/glossary/term/least_privilege](https://csrc.nist.gov/glossary/term/least_privilege) + +As such, the following API permissions are used by default: + +### Default Azure Application Permissions + +| API / Permissions name | Type | Description | Admin consent required | +|---|---|---|---| +| Files.Read | Delegated | Have read-only access to user files | No | +| Files.Read.All | Delegated | Have read-only access to all files user can access | No | +| Sites.Read.All | Delegated | Have read-only access to all items in all site collections | No | +| offline_access | Delegated | Maintain access to data you have given it access to | No | + +![default_authentication_scopes](./images/default_authentication_scopes.jpg) + +### Default User Authentication Permissions + +| API / Permissions name | Type | Description | Admin consent required | +|---|---|---|---| +| Files.ReadWrite | Delegated | Have full access to user files | No | +| Files.ReadWrite.All | Delegated | Have full access to all files user can access | No | +| Sites.ReadWrite.All | Delegated | Have full access to all items in all site collections | No | +| offline_access | Delegated | Maintain access to data you have given it access to | No | + +When these delegated API permissions are commbined, these provide the effective authentication scope for the OneDrive Client for Linux to access your data. The effective 'default' permissions will be: + +| API / Permissions name | Type | Description | Admin consent required | +|---|---|---|---| +| Files.ReadWrite | Delegated | Have full access to user files | No | +| Files.ReadWrite.All | Delegated | Have full access to all files user can access | No | +| Sites.ReadWrite.All | Delegated | Have full access to all items in all site collections | No | +| offline_access | Delegated | Maintain access to data you have given it access to | No | + +These 'default' permissions will allow the OneDrive Client for Linux to read, write and delete data associated with your OneDrive Account. + +## Configuring read-only access to your OneDrive data +In some situations, it may be desirable to configure the OneDrive Client for Linux totally in read-only operation. + +To change the application to 'read-only' access, add the following to your configuration file: +```text +read_only_auth_scope = "true" +``` + +This will change the user authentication scope requect to use read-only access. When using read-only authentication scopes, the uploading of any data or local change to OneDrive will fail. + +**Note:** When changing this value, you *must* re-authenticate the client using the `--reauth` option to utilise the change in authentication scopes. + +**Important:** You also will need to remove your existing application access consent otherwise old authentication consent will still be used and you will still be able to upload changes to OneDrive. + +## Reviewing your existing application access consent + +To review your existing application access consent, you need to access the following URL: https://account.live.com/consent/Manage + +From here, you are able to review what applications have been given what access to your data, and remove application access as required. diff --git a/docs/images/authentication_scopes.jpg b/docs/images/authentication_scopes.jpg index ae3e5870..20e40d07 100644 Binary files a/docs/images/authentication_scopes.jpg and b/docs/images/authentication_scopes.jpg differ diff --git a/docs/images/default_authentication_scopes.jpg b/docs/images/default_authentication_scopes.jpg new file mode 100644 index 00000000..edccddde Binary files /dev/null and b/docs/images/default_authentication_scopes.jpg differ diff --git a/docs/national-cloud-deployments.md b/docs/national-cloud-deployments.md index 6327b076..d7d6644c 100644 --- a/docs/national-cloud-deployments.md +++ b/docs/national-cloud-deployments.md @@ -35,9 +35,8 @@ Configure the API permissions as per the following: |---|---|---|---| | Files.ReadWrite | Delegated | Have full access to user files | No | | Files.ReadWrite.All | Delegated | Have full access to all files user can access | No | +| Sites.ReadWrite.All | Delegated | Have full access to all items in all site collections | No | | offline_access | Delegated | Maintain access to data you have given it access to | No | -| Sites.Read.All | Delegated | Read items in all site collections | No | -| Sites.ReadWrite.All | Delegated | Edit or delete items in all site collections | No | ![authentication_scopes](./images/authentication_scopes.jpg) diff --git a/src/config.d b/src/config.d index 259d2a09..07785b20 100644 --- a/src/config.d +++ b/src/config.d @@ -136,6 +136,8 @@ final class Config longValues["webhook_renewal_interval"] = 3600 * 12; // Log to application output running configuration values boolValues["display_running_config"] = false; + // Configure read-only authentication scope + boolValues["read_only_auth_scope"] = false; // DEVELOPER OPTIONS // display_memory = true | false diff --git a/src/main.d b/src/main.d index 052a8413..ba45e9aa 100644 --- a/src/main.d +++ b/src/main.d @@ -678,6 +678,7 @@ int main(string[] args) writeln("Config option 'monitor_fullscan_frequency' = ", cfg.getValueLong("monitor_fullscan_frequency")); // sync process and method + writeln("Config option 'read_only_auth_scope' = ", cfg.getValueBool("read_only_auth_scope")); writeln("Config option 'dry_run' = ", cfg.getValueBool("dry_run")); writeln("Config option 'upload_only' = ", cfg.getValueBool("upload_only")); writeln("Config option 'download_only' = ", cfg.getValueBool("download_only")); diff --git a/src/onedrive.d b/src/onedrive.d index d9defdfd..f5278325 100644 --- a/src/onedrive.d +++ b/src/onedrive.d @@ -557,7 +557,17 @@ final class OneDriveApi { import std.stdio, std.regex; char[] response; - string url = authUrl ~ "?client_id=" ~ clientId ~ "&scope=Files.ReadWrite%20Files.ReadWrite.all%20Sites.Read.All%20Sites.ReadWrite.All%20offline_access&response_type=code&prompt=login&redirect_uri=" ~ redirectUrl; + string authScope; + // What authentication scope to use? + if (cfg.getValueBool("read_only_auth_scope")) { + // read-only authentication scopes has been requested + authScope = "&scope=Files.Read%20Files.Read.All%20Sites.Read.All%20offline_access&response_type=code&prompt=login&redirect_uri="; + } else { + // read-write authentication scopes will be used (default) + authScope = "&scope=Files.ReadWrite%20Files.ReadWrite.All%20Sites.ReadWrite.All%20offline_access&response_type=code&prompt=login&redirect_uri="; + } + + string url = authUrl ~ "?client_id=" ~ clientId ~ authScope ~ redirectUrl; string authFilesString = cfg.getValueString("auth_files"); string authResponseString = cfg.getValueString("auth_response"); if (authResponseString != "") { @@ -599,7 +609,7 @@ final class OneDriveApi // match the authorization code auto c = matchFirst(response, r"(?:[\?&]code=)([\w\d-.]+)"); if (c.empty) { - log.log("Invalid uri"); + log.log("Invalid response uri entered"); return false; } c.popFront(); // skip the whole match @@ -1081,6 +1091,25 @@ final class OneDriveApi } if (response.type() == JSONType.object) { + // Has the client been configured to use read_only_auth_scope + if (cfg.getValueBool("read_only_auth_scope")) { + // read_only_auth_scope has been configured + if ("scope" in response){ + string effectiveScopes = response["scope"].str(); + // Display the effective authentication scopes + writeln("\nEffective API Authentication Scopes: ", effectiveScopes); + // if we have any write scopes, we need to tell the user to update an remove online prior authentication and exit application + if (canFind(effectiveScopes, "Write")) { + // effective scopes contain write scopes .. so not a read-only configuration + writeln("\nERROR: You have authentication scopes that allow write operations. You need to remove your existing application access consent"); + writeln("\nPlease login to https://account.live.com/consent/Manage and remove your existing application access consent\n"); + // force exit + shutdown(); + exit(-1); + } + } + } + if ("access_token" in response){ accessToken = "bearer " ~ response["access_token"].str(); refreshToken = response["refresh_token"].str();