diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..4aa6ecc05 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +./.github/ @recrwplay diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..1e63f2a92 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + groups: + prod-dependencies: + dependency-type: "production" + dev-dependencies: + dependency-type: "development" diff --git a/.github/workflows/docs-branch-checks.yml b/.github/workflows/docs-branch-checks.yml new file mode 100644 index 000000000..caa09013d --- /dev/null +++ b/.github/workflows/docs-branch-checks.yml @@ -0,0 +1,52 @@ +# This is an example of the docs-pr.yml workflow available from the recrwplay org +name: "Verify Branch" + +on: + # push: + # branches: + # - dev + # schedule: + # - cron: '00 16 * * *' + workflow_dispatch: + inputs: + html: + description: 'Generate HTML' + type: boolean + required: false + default: true + links: + description: 'Check links' + type: boolean + required: false + default: true + lint: + description: 'Lint docs' + type: boolean + required: false + default: false + +jobs: + + docs-build: + if: ${{ inputs.html || github.event_name == 'push' }} + name: Generate HTML + uses: neo4j/docs-tools/.github/workflows/reusable-docs-build.yml@v1.2.0 + with: + retain-artifacts: 14 + deploy-id: 0 + + docs-verify: + name: Verify HTML + needs: docs-build + uses: neo4j/docs-tools/.github/workflows/reusable-docs-verify.yml@v1.2.0 + + docs-links: + if: ${{ inputs.links || github.event_name == 'push' }} + name: Check links + needs: docs-build + uses: neo4j/docs-tools/.github/workflows/reusable-docs-links.yml@v1.2.0 + + docs-lint: + if: ${{ inputs.lint || github.event_name == 'push' }} + name: Lint docs + uses: neo4j/docs-tools/.github/workflows/reusable-docs-lint.yml@v1.2.0 diff --git a/.github/workflows/docs-deploy-surge.yml b/.github/workflows/docs-deploy-surge.yml index cfc2845cd..64a4ea746 100644 --- a/.github/workflows/docs-deploy-surge.yml +++ b/.github/workflows/docs-deploy-surge.yml @@ -1,67 +1,126 @@ # Use this starter workflow to deploy HTML generated by Antora to surge.sh # Docs are published at --.surge.sh -# By default, this workflow runs on completion of a workflow called "Verify PR" -# This workflow expects the triggering workflow to generate an artifact called "docs" +# By default, this workflow runs on completion of a workflow called "Verify docs PR" + +# This workflow expects the triggering workflow to generate an artifact called "docs" # - update the reference to "docs" and "docs.zip" in this workflow if your triggering workflow generates an artifact with a different name -name: "Deploy to surge" + +# change to force workflow with no changelog + +name: "Deploy docs preview" on: workflow_run: - workflows: ["Verify PR"] + workflows: ["Verify docs PR"] types: - completed jobs: publish-docs: + # Uncomment this if statement to deploy only when the PR builds cleanly # if: github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest steps: - name: "Download built documentation" - uses: actions/github-script@v6.0.0 + uses: actions/github-script@v7 + env: + RUN_ID: ${{ github.event.workflow_run.id }} + WORKSPACE: ${{ github.workspace }} with: script: | var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, - run_id: ${{ github.event.workflow_run.id }}, + run_id: ${{ env.RUN_ID }}, }); - var matchArtifact = artifacts.data.artifacts.filter((artifact) => { + + var matchArtifactDocs = artifacts.data.artifacts.filter((artifact) => { return artifact.name == "docs" })[0]; - var download = await github.rest.actions.downloadArtifact({ + var downloadDocs = await github.rest.actions.downloadArtifact({ owner: context.repo.owner, repo: context.repo.repo, - artifact_id: matchArtifact.id, + artifact_id: matchArtifactDocs.id, archive_format: 'zip', }); var fs = require('fs'); - fs.writeFileSync('${{ github.workspace }}/docs.zip', Buffer.from(download.data)); - - - run: unzip docs.zip - + fs.writeFileSync('${{ env.WORKSPACE }}/docs.zip', Buffer.from(downloadDocs.data)); + + var matchArtifactChangelog = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "changelog" + })[0]; + var downloadChangelog = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifactChangelog.id, + archive_format: 'zip', + }); + fs.writeFileSync('${{ env.WORKSPACE }}/changelog.zip', Buffer.from(downloadChangelog.data)); + + - id: unzip-docs + run: unzip docs.zip + + - id: get-top-dir + run: | + root=$(ls -d */index.html | sed -r 's/(.*)\/index\.html/\1/') + echo "top-dir=$root" >> $GITHUB_OUTPUT + + - id: unzip-changelog + if: ${{ hashFiles('changelog.zip') != '' }} + run: unzip changelog.zip - id: get-deploy-id run: | deployid=$(> "$GITHUB_OUTPUT" + + - id: get-deploy-url + env: + ORG: ${{ github.event.repository.owner.login }} + REPO: ${{ github.event.repository.name }} + DEPLOYID: ${{ steps.get-deploy-id.outputs.deploy-id }} + run: | + deployurl=$ORG-$REPO-$DEPLOYID.surge.sh + echo "deploy-url=$deployurl" >> $GITHUB_OUTPUT + - uses: actions/setup-node@v4 with: node-version: lts/* - + - name: Deploy docs to surge + shell: bash + env: + DEPLOY_URL: ${{ steps.get-deploy-url.outputs.deploy-url }} + SURGE_TOKEN: "${{ secrets.DOCS_SURGE_TOKEN }}" + SITE_DIR: ${{ steps.get-top-dir.outputs.top-dir }} run: | npm install -g surge - surge ./site ${{ github.event.repository.owner.login}}-${{ github.event.repository.name}}-${{ steps.get-deploy-id.outputs.deploy-id }}.surge.sh --token ${{ secrets.SURGE_TOKEN }} + surge ./$SITE_DIR $DEPLOY_URL --token "$SURGE_TOKEN" - - name: Comment on PR - uses: marocchino/sticky-pull-request-comment@v2 + # If the PR artifacts include a changelog file, add it to the PR as a comment + # The changelog contains links to new and changed files in the deployed docs + - name: Comment on PR (changelog) + if: ${{ hashFiles('changelog') != '' }} + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0 with: number: ${{ steps.get-deploy-id.outputs.deploy-id }} + recreate: true + header: docs-pr-changes + path: changelog + GITHUB_TOKEN: ${{ secrets.DOCS_PR_COMMENT_TOKEN }} + + # If there's no changelog, add a generic comment to the PR + - name: Comment on PR (no changelog) + if: ${{ hashFiles('changelog') == '' }} + env: + DEPLOY_URL: ${{ steps.get-deploy-url.outputs.deploy-url }} + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0 + with: + number: ${{ steps.get-deploy-id.outputs.deploy-id }} + header: docs-pr-changes message: | Looks like you've updated the documentation! - - Check out your changes at https://${{ github.event.repository.owner.login}}-${{ github.event.repository.name}}-${{ steps.get-deploy-id.outputs.deploy-id }}.surge.sh - GITHUB_TOKEN: ${{ secrets.PR_COMMENT_TOKEN }} + Check out your changes at https://${{ env.DEPLOY_URL }} + GITHUB_TOKEN: ${{ secrets.DOCS_PR_COMMENT_TOKEN }} diff --git a/.github/workflows/docs-pr-checks.yml b/.github/workflows/docs-pr-checks.yml new file mode 100644 index 000000000..a98780604 --- /dev/null +++ b/.github/workflows/docs-pr-checks.yml @@ -0,0 +1,61 @@ + +name: "Verify docs PR" + +on: + pull_request: + branches: + - 'dev' + - 'main' + - '5.x' + - '4.4' + +jobs: + + # Generate HTML + docs-build-pr: + uses: neo4j/docs-tools/.github/workflows/reusable-docs-build.yml@v1.2.0 + with: + deploy-id: ${{ github.event.number }} + retain-artifacts: 14 + + # Parse the json log output from the HTML build, and output warnings and errors as annotations + # Optionally, fail the build if there are warnings or errors + # By default, the job fails if there are errors, passes if there are warnings only. + docs-verify-pr: + needs: docs-build-pr + uses: neo4j/docs-tools/.github/workflows/reusable-docs-verify.yml@v1.2.0 + with: + failOnWarnings: true + + # Get lists of changes in the PR + # - all updated asciidoc files + # - all updated asciidoc pages + # - all new asciidoc pages + docs-changes-pr: + runs-on: ubuntu-latest + outputs: + asciidoc-files: ${{ steps.get-file-changes.outputs.asciidoc_all_changed_files }} + pages-modified: ${{ steps.get-file-changes.outputs.pages_modified_files }} + pages-added: ${{ steps.get-file-changes.outputs.pages_added_files }} + steps: + - name: Get file changes + id: get-file-changes + uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1 + with: + separator: ',' + files_yaml: | + pages: + - modules/**/pages/**/*.adoc + asciidoc: + - modules/**/*.adoc + + # Generate a PR comment if the docs are using the pageList extension + # The extension maps asciidoc source files to their HTML output paths + # The comment will contain links to new and changed pages in the deployed HTML docs + docs-updates-comment-pr: + if: needs.docs-build-pr.outputs.pages-listed == 'success' + needs: [docs-build-pr, docs-changes-pr] + uses: neo4j/docs-tools/.github/workflows/reusable-docs-pr-changes.yml@v1.2.0 + with: + pages-modified: ${{ needs.docs-changes-pr.outputs.pages-modified }} + pages-added: ${{ needs.docs-changes-pr.outputs.pages-added }} diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml deleted file mode 100644 index 85f5dd246..000000000 --- a/.github/workflows/docs-pr.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Use this starter workflow to verify PRs that include a change to the docs -# The default setup runs against PRs targeting your default branch -# Default artifact retention is 7 days - -name: "Verify PR" - -on: - pull_request: - branches: - - "4.4" - - "5.0" - - "5.x" - - "dev" - -jobs: - - # note that the build job requires a build-verify script in package.json - # build-verify should build html with Antora, and output a .json log file - # eg 'antora playbook.yml --log-format=json --log-file ./build/log/log.json' - docs-build-for-pr: - uses: recrwplay/actions-demo/.github/workflows/reusable-docs-build.yml@main - with: - deploy-id: ${{ github.event.number }} - retain-artifacts: 14 - - docs-verify-for-pr: - needs: docs-build-for-pr - uses: recrwplay/actions-demo/.github/workflows/reusable-docs-verify.yml@main - with: - failOnWarnings: true diff --git a/.github/workflows/docs-teardown.yml b/.github/workflows/docs-teardown.yml index db50b305d..bee70755a 100644 --- a/.github/workflows/docs-teardown.yml +++ b/.github/workflows/docs-teardown.yml @@ -4,10 +4,10 @@ name: "Documentation Teardown" on: pull_request_target: branches: - - "4.4" - - "5.0" - - "5.x" - - "dev" + - 'dev' + - 'main' + - '5.x' + - '4.4' types: - closed @@ -16,11 +16,34 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: lts/* + + - id: get-deploy-url + env: + ORG: ${{ github.event.repository.owner.login }} + REPO: ${{ github.event.repository.name }} + DEPLOYID: ${{ github.event.pull_request.number }} + run: | + deployurl=$ORG-$REPO-$DEPLOYID.surge.sh + echo "deploy-url=$deployurl" >> $GITHUB_OUTPUT - name: Teardown documentation + shell: bash + env: + SURGE_TOKEN: "${{ secrets.DOCS_SURGE_TOKEN }}" + DEPLOY_URL: ${{ steps.get-deploy-url.outputs.deploy-url }} run: | npm install -g surge - surge teardown ${{ github.event.repository.owner.login}}-${{ github.event.repository.name}}-${{ github.event.pull_request.number }}.surge.sh --token ${{ secrets.SURGE_TOKEN }} - + surge teardown $DEPLOY_URL --token "$SURGE_TOKEN" + + - name: Comment on PR + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0 + with: + number: ${{ github.event.pull_request.number }} + header: docs-pr-changes + message: | + Thanks for the documentation updates. + + The preview documentation has now been torn down - reopening this PR will republish it. + GITHUB_TOKEN: ${{ secrets.DOCS_PR_COMMENT_TOKEN }} diff --git a/.gitignore b/.gitignore index 40e4a191c..61439e09f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,12 @@ shared/ src/main/_common-and-old/ tags target/ +.vscode/ -# node modules +# docs project +.env node_modules/ -.env \ No newline at end of file +package-lock.json + +# use worktrees for clones of content from other branches so Antora can access it +worktrees/ \ No newline at end of file diff --git a/README.adoc b/README.adoc index 18d012070..fe344139d 100644 --- a/README.adoc +++ b/README.adoc @@ -35,80 +35,3 @@ When you run `npm start`, the project is monitored for updates to asciidoc files If a change to an asciidoc file is detected the site is automatically rebuilt. -== Generating asciidoc source files - -If you are creating new documentation from scratch, creating all the asciidoc files can be time-consuming. -This repo contains a script that you can use to save time by generating skeleton asciidoc files from your navigation. - -To use the script, first create your navigation file, or files if your doc set has more than one component. To use the script, all navigation files should have the filename `content-nav.adoc`. -Then, to create the asciidoc source files, run `npm run adoc-gen`. - -For every file that is included as a list item entry in a `content-nav.adoc` file, an asciidoc file is created in the location specified. -For example, if _modules/ROOT/content-nav.adoc_ includes `+++* xref:installation/introduction.adoc[]+++`, a file is created at _modules/ROOT/pages/installation/introduction.adoc_. - -The file contents consist of a comment to indicate that the file was generated by the script, and a top level title element. -If title text is specified in the entry in the navigation file, that value will be used for the title in the generated file. -If no title text is specified, the default title text is taken from the filename, formatted with sentence capitalization. - -== Configuring your project - -You'll need to update the following for your project - -=== antora.yml - -- `name:` - replace `docs-template` with the name of the project as it will appear in the URL https://neo4j.com/docs/`, for example 'getting-started', 'cypher-manual'. -- `title:` - the title of the manual, for example Getting Started Guide, Cypher Manual. This value is displayed in the breadcrumbs above each page. -- `version:` - the version of the content that is generated from the branch containing this `antora.yml` file. - -Optionally, you can add the following attributes: - -- `display_version:` - Use this attribute when you want the version that is displayed in your content and in the UI to be different from the version that appears in the URL. For example, you might want to use _/2.0/_ in URLs, but display the version as `2.0-beta` in the version selector drop-down. -- `prerelease:` - if you publish multiple versions of this project, you can mark a version as being a prerelease, by adding `prerelease: true`. The content is published alongside the other versions, but does not appear in the drop-down version selector, and is not included when Antora is calculating the default (or 'latest') version in order to resolve links between pages. For more information, see link:https://docs.antora.org/antora/latest/component-prerelease/[Antora // Docs -> Identify a Prerelease Version] - -=== preview.yml - -Antora uses a link:https://docs.antora.org/antora/latest/playbook/[playbook] to determine what content is included in a site, and the appearance of that content. - -In our projects, we use `preview.yml` as the default playbook name. - -Update the `start_page` attribute to match the value of the `name` attribute in your `antora.yml` file. - ----- -site: - start_page: docs-template:ROOT:index.adoc ----- - -Update the information for the sitemap extension: - ----- -antora: - extensions: - - require: "@neo4j-antora/antora-modify-sitemaps" - sitemap_version: '1.0' - sitemap_loc_version: 'current' - move_sitemaps_to_components: true ----- - -The link:https://www.npmjs.com/package/@neo4j-antora/antora-modify-sitemaps[`antora-modify-sitemaps`] Antora extension generates sitemaps for Neo4j docs that include information about the current release only, and makes sure those sitemaps are included in the right output folder when the HTML is built. -In this example, a sitemap file would be generated at _build/site/docs-template/1.0/sitemap.xml_. -Change the value of `sitemap_version` to the 'current' release version of your project. -For example, Neo4j manuals such as the Getting Started Guide or Cypher Manual use 4.4 as their current version, so for those manuals this is set as `sitemap_version: '4.4`. - -=== [Optional] Add an 'Edit this page' link - -If your repo is public, you can add an `Edit this page` link to your pages to encourage external contributors, and to provide a quick way for users to suggest changes. - -Update the following attribute in your playbook: - ----- -asciidoc: - attributes: - page-origin-private: false ----- - -=== [Optional] Add a 'preview' note to each page - -When we publish preview content to either development or production environments, we prepend an admonition to every page to make it clear that this is preview content, for example, as in link:https://neo4j.com/docs/graph-data-science/2.0-preview/[Graph Data Science 2.0-preview]. - -You can use the link:https://www.npmjs.com/package/@neo4j-antora/antora-add-notes[antora-add-notes] extension to add content to your pages. -Follow the Usage instructions in the package documentation. diff --git a/antora.yml b/antora.yml index 22f773682..98bea761d 100644 --- a/antora.yml +++ b/antora.yml @@ -1,13 +1,15 @@ name: operations-manual title: Operations Manual version: '5' +display_version: '5.26' +lts: true start_page: ROOT:index.adoc nav: - modules/ROOT/content-nav.adoc asciidoc: attributes: neo4j-version: '5' - neo4j-version-minor: '5.1' - neo4j-version-exact: '5.1.0' - neo4j-buildnumber: '5.1' - neo4j-debian-package-version: '1:5.1.0@' + neo4j-version-minor: '5.26' + neo4j-version-exact: '5.26.8' + neo4j-buildnumber: '5.26' + neo4j-debian-package-version: '1:5.22.0@' diff --git a/models/hospital/README.txt b/models/hospital/README.txt new file mode 100644 index 000000000..3248eb5f6 --- /dev/null +++ b/models/hospital/README.txt @@ -0,0 +1,65 @@ +============================================================================================================================================== +THIS EXAMPLE IS USED IN THE DOCUMENTATION ONLY AS A REFERENCE AND AS BASIS FOR THE ACCESS CONTROL TUTORIAL (see xref:tutorial/access-control.adoc). +IT IS NOT INTENDED TO BE USED NEITHER IN PRODUCTION NOR FOR ANY OTHER PURPOSES. +============================================================================================================================================== + + + +Hospital Database With Security +=============================== + +This model is for an example hospital database with fine-grained sub-graph +security used to control access to parts of the data based on roles and +privileges. + +This forms the background data model for the documentation found at +https://neo4j.com/docs/operations-manual/5/authentication-authorization/ + +Cypher Scripts +-------------- + +There are two main types of scripts, those running against `system` used to +setup the users, roles and security privileges, and those running against +the `healthcare` database for setting up the data model itself. These +scripts do not include the queries used by the different users to query the +database. See the docs at +https://neo4j.com/docs/operations-manual/current/authentication-authorization/ +for example queries. + +Run as `neo4j` against the `system` database: + +* setup_healthcare.cypher +* setup_healthcare_privileges.cypher + +Run as `neo4j` against the `healthcare` database: + +* make_healthcare.cypher +* make_healthcare_meta.cypher + +The easiest way to run all scripts is to run the two shell scripts: + +* ./setup_healthcare.sh +* ./run_roles.sh + +The first will run all the setup and make scripts on the system and +healthcare database to create a complete working model with users, roles and +privileges in the system database, and patients, diseases and symptoms in +the healthcare database. + +The second script will run through a set of roles, and for each use a +pre-defined user, grant it the role, find a file named +healthcare_queries_$role.cypher and as that user it will run all commands in +that file against the healthcare database. This allows you to test +everything required in the above mentioned chapter and copy and paste all +query results directly into the chapter contents. + +Setting up Neo4j +---------------- + +Note that the above script assume that the Neo4j server has been configured +to run on non startard ports so that it does not conflict with the documentation build itself. +In particular the bolt port is 7688. +See the contents of the file healthcare_config.sh for the settings, and change any +that you feel are more appropriate to your server configuration (or change your server to match +this configurations). + diff --git a/modules/ROOT/pages/authentication-authorization/access-control.adoc b/models/hospital/access-control-old.adoc similarity index 98% rename from modules/ROOT/pages/authentication-authorization/access-control.adoc rename to models/hospital/access-control-old.adoc index 839a5c82a..0c41777a1 100644 --- a/modules/ROOT/pages/authentication-authorization/access-control.adoc +++ b/models/hospital/access-control-old.adoc @@ -1,11 +1,11 @@ [role=enterprise-edition] [[auth-access-control]] = Fine-grained access control -:description: Describes an example that illustrates various aspects of security and fine-grained access control. +:description: Describes an example that illustrates various aspects of security and fine-grained access control. When creating a database, administrators may want to establish which users have the ability to access certain information. -As described in xref:authentication-authorization/built-in-roles/auth-built-in-roles[Built-in roles], Neo4j already offers preset roles configured to specific permissions (i.e. read, edit, or write). +As described in xref:authentication-authorization/built-in-roles.adoc[Built-in roles], Neo4j already offers preset roles configured to specific permissions (i.e. read, edit, or write). While these built-in roles cover many common daily scenarios, it is also possible to create custom roles for specific needs. This page contains an example that illustrates various aspects of security and fine-grained access control. @@ -35,7 +35,7 @@ They can be described using the properties: * `description` `(:Disease)`:: -Known illnesses mapped in a catalog found in the database. +Known illnesses mapped in a catalog found in the database. They can be described using the properties: + * `name` @@ -85,7 +85,7 @@ This allows users to be created entirely within the database security model, a s For more information, see link:/docs/cypher-manual/{neo4j-version}/access-control/[Cypher Manual -> Access control]. The following examples show two different approaches to using Neo4j security features to support the _healthcare_ database application. -The first approach uses xref:authentication-authorization/built-in-roles/auth-built-in-roles[Built-in roles], whereas the second uses more advanced resources with fine-grained privileges for <>. +The first approach uses xref:authentication-authorization/built-in-roles.adoc[Built-in roles], whereas the second uses more advanced resources with fine-grained privileges for <>. In this example, consider five users of the _healthcare_ database: @@ -128,13 +128,13 @@ Neo4j comes with built-in roles that cover a number of common needs: * `architect` - Has all the capabilities of the publisher as well as the ability to manage indexes and constraints. * `admin` - Can perform architect actions as well as manage databases, users, roles, and privileges. -Consider Charlie from the example of users. +Consider Charlie from the example of users. As a researcher, they do not need write access to the database, so they are assigned the `reader` role. -On the other hand, Alice (the doctor), Daniel (the nurse), and Bob (the receptionist) all need to update the database with new patient information, but do not need to expand the schema with new labels, relationship types, property names or indexes. +On the other hand, Alice (the doctor), Daniel (the nurse), and Bob (the receptionist) all need to update the database with new patient information, but do not need to expand the schema with new labels, relationship types, property names or indexes. For this reason, they are all assigned the `editor` role. -Tina, the IT administrator who installs and manages the database, needs to be assigned the `admin` role. +Tina, the IT administrator who installs and manages the database, needs to be assigned the `admin` role. Here is how to grant roles to the users: @@ -183,11 +183,11 @@ Has the permission to save _diagnoses_ to the database, but not expand the schem Receptionist:: Should be able to read and write all patient data, but not be able to see the symptoms, diseases, or diagnoses. Researcher:: -Should be able to perform statistical analysis of all data, except patients’ personal information, to which they should have restricted access. +Should be able to perform statistical analysis of all data, except patients’ personal information, to which they should have restricted access. To illustrate two different ways of setting up the same effective privileges, two roles are created for comparison. Nurse:: Should be able to perform all tasks that both the doctor and the receptionist can do. -Granting both roles (doctor and receptionist) to the nurse does not work as expected. +Granting both roles (doctor and receptionist) to the nurse does not work as expected. This is explained in the section dedicated to the creation of the `nurse` role. Junior nurse:: While the senior nurse is able to save diagnoses just as a doctor can, some (junior) nurses might not be allowed to do that. @@ -709,7 +709,7 @@ RETURN n.name, n.ssn, n.address, n.dateOfBirth; [[detach-delete-restricted-user]] -With the `receptionist` role, Bob can delete any new patient nodes they have just created, but they are not able to delete patients that have already received diagnoses since those are connected to parts of the graph that Bob cannot see. +With the `receptionist` role, Bob can delete any new patient nodes they have just created, but they are not able to delete patients that have already received diagnoses since those are connected to parts of the graph that Bob cannot see. Here is a demonstration of both scenarios: [source, cypher] diff --git a/models/hospital/healthcare_config.sh b/models/hospital/healthcare_config.sh new file mode 100755 index 000000000..7415eac28 --- /dev/null +++ b/models/hospital/healthcare_config.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +INDEXES_LABELS="Patient Symptom Disease" +DB_NAME="healthcare" +NEO4J_USERNAME=neo4j +NEO4J_PASSWORD=my-secret +NEO4J_BOLT_PORT=7688 +NEO4J_ADDRESS=neo4j://localhost:$NEO4J_BOLT_PORT +NEO4J_CONNECT="-u $NEO4J_USERNAME -p $NEO4J_PASSWORD -a $NEO4J_ADDRESS" +DB_CONNECT="-d $DB_NAME $NEO4J_CONNECT" +SY_CONNECT="-d system $NEO4J_CONNECT" +ENABLE_CLUSTERING=true + +# If these scripts are copied into the root of a neo4j intallation use bin/cypher-shell +# Otherwise use an absolute path like: CYPHER_SHELL=/home/path/to/neo4j-enterprise-5.26.2/bin/cypher-shell +CYPHER_SHELL=bin/cypher-shell + +# to have a custom config that should not be checked into git, create a file called healthcare_local.sh +# and fill it with overriding settings. For example one cluster config we tested on AWS used the following: +#NEO4J_ADDRESS=bolt://ec2-52-214-104-194.eu-west-1.compute.amazonaws.com:10000 +#NEO4J_CONNECT="-u $NEO4J_USERNAME -p $NEO4J_PASSWORD -a $NEO4J_ADDRESS" +#DB_CONNECT="-d $DB_NAME $NEO4J_CONNECT" +#SY_CONNECT="-d system $NEO4J_CONNECT" +#CYPHER_SHELL=/home/path/to/neo4j-enterprise-5.26.2/bin/cypher-shell + +if [ -f ./healthcare_local.sh ] ; then + source ./healthcare_local.sh +fi + +if [ -f ./healthcare_detected.sh ] ; then + source ./healthcare_detected.sh +fi diff --git a/models/hospital/healthcare_queries_broken.cypher b/models/hospital/healthcare_queries_broken.cypher new file mode 100644 index 000000000..d6d1270e4 --- /dev/null +++ b/models/hospital/healthcare_queries_broken.cypher @@ -0,0 +1,15 @@ +// +// The nurse is supposed to be able to perform both doctor and receptionist actions +// But this 'broken' nurse is made by combining the two roles 'doctor' and 'receptionist' +// with undesired consequences. They keep the restrictions of the doctor! +// + +// Daniel can read patient records, but not see their addresses + +RETURN "Finding patients, but not addresses" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + + diff --git a/models/hospital/healthcare_queries_doctor.cypher b/models/hospital/healthcare_queries_doctor.cypher new file mode 100644 index 000000000..bae5a2931 --- /dev/null +++ b/models/hospital/healthcare_queries_doctor.cypher @@ -0,0 +1,42 @@ +// +// The doctor should not be able to see some patient data, but can perform diagnoses +// + +// Reading the whole database should only show patients, symptoms and diseases + +RETURN "Counting all labels" AS `------------------------------------------------`; + +MATCH (n) WITH labels(n) AS labels +RETURN labels, count(*); + +// Alice can read patient records, but not see their addresses + +RETURN "Finding patients, but not addresses" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + +// Alice can perform a diagnoses, by searching the symptoms and finding likely diseases + +RETURN "Find likely diseases" AS `------------------------------------------------`; + +MATCH (x:Patient) WHERE NOT (x)-[:DIAGNOSIS]->() WITH x.ssn as ssn SKIP 10 LIMIT 1 +MATCH (n:Patient)-[:HAS]->(s:Symptom)-[:OF]->(d:Disease) + WHERE n.ssn = ssn +RETURN n.ssn, n.name, d.name, count(s) AS score ORDER BY score DESC; + +RETURN "Save diagnosis" AS `------------------------------------------------`; + +WITH datetime({epochmillis:timestamp()}) AS now +WITH now, date(now) as today +MATCH (p:Patient) + WHERE p.ssn = 1234657 +MATCH (d:Disease) + WHERE d.name = "Chronic Placeboitis" +MERGE (p)-[i:DIAGNOSIS {by: 'Alice'}]->(d) + ON CREATE SET i.created_at = now, i.updated_at = now, i.date = today + ON MATCH SET i.updated_at = now +RETURN p.name, d.name, i.by, i.date, duration.between(i.created_at, i.updated_at) AS updated; + + diff --git a/models/hospital/healthcare_queries_itadmin.cypher b/models/hospital/healthcare_queries_itadmin.cypher new file mode 100644 index 000000000..f9f1bd811 --- /dev/null +++ b/models/hospital/healthcare_queries_itadmin.cypher @@ -0,0 +1,20 @@ +// +// The IT-Admin can do everything except see SSN +// + +// Tina can read patient records, but not see their SSN + +RETURN "Finding patients, but not SSN" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + +// Tina can read patients and diseases but cannot create DIAGNOSIS relationships + +RETURN "Finding patients and diseases, but cannot create DIAGNOSIS" AS `------------------------------------------------`; + +MATCH (n:Patient), (d:Disease) +CREATE (n)-[:DIAGNOSIS]->(d); + + diff --git a/models/hospital/healthcare_queries_junior.cypher b/models/hospital/healthcare_queries_junior.cypher new file mode 100644 index 000000000..89d8ea7c5 --- /dev/null +++ b/models/hospital/healthcare_queries_junior.cypher @@ -0,0 +1,35 @@ +// +// The nurse is supposed to be able to perform both doctor and receptionist actions. +// This is basically the doctor without restrictions. +// + +// Daniel can read patient records, and see their addresses + +RETURN "Finding patients, and see addresses" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + +// Daniel can perform a diagnoses, by searching the symptoms and finding likely diseases + +RETURN "Find likely diseases" AS `------------------------------------------------`; + +MATCH (x:Patient) WHERE NOT (x)-[:DIAGNOSIS]->() WITH x.ssn as ssn SKIP 10 LIMIT 1 +MATCH (n:Patient)-[:HAS]->(s:Symptom)-[:OF]->(d:Disease) + WHERE n.ssn = ssn +RETURN n.ssn, n.name, d.name, count(s) AS score ORDER BY score DESC; + +// Daniel can NOT save diagnoses when he is a JUNIOR nurse + +RETURN "Save diagnosis" AS `------------------------------------------------`; + +WITH date(datetime({epochmillis:timestamp()})) AS today +MATCH (p:Patient) + WHERE p.ssn = 1234650 +MATCH (d:Disease) + WHERE d.name = "Chronic Placeboitis" +MERGE (p)-[i:DIAGNOSIS {by: 'Daniel'}]->(d) + ON CREATE SET i.date = today +RETURN p.name, d.name, i.by, i.date; + diff --git a/models/hospital/healthcare_queries_nurse.cypher b/models/hospital/healthcare_queries_nurse.cypher new file mode 100644 index 000000000..de3de30a6 --- /dev/null +++ b/models/hospital/healthcare_queries_nurse.cypher @@ -0,0 +1,27 @@ +// +// The nurse is supposed to be able to perform both doctor and receptionist actions. +// This is basically the doctor without restrictions. +// + +// Daniel can read patient records, and see their addresses + +RETURN "Finding patients, and see addresses" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + +// Daniel can save diagnoses just like Alice + +RETURN "Save diagnosis" AS `------------------------------------------------`; + +WITH date(datetime({epochmillis:timestamp()})) AS today +MATCH (p:Patient) + WHERE p.ssn = 1234657 +MATCH (d:Disease) + WHERE d.name = "Chronic Placeboitis" +MERGE (p)-[i:DIAGNOSIS {by: 'Daniel'}]->(d) + ON CREATE SET i.date = today +RETURN p.name, d.name, i.by, i.date; + + diff --git a/models/hospital/healthcare_queries_receptionist.cypher b/models/hospital/healthcare_queries_receptionist.cypher new file mode 100644 index 000000000..cb08d659f --- /dev/null +++ b/models/hospital/healthcare_queries_receptionist.cypher @@ -0,0 +1,80 @@ +// +// The receptionist should only read/write patient data +// + +// Reading the whole database should only show patients + +RETURN "Counting all labels" AS `------------------------------------------------`; + +MATCH (n) WITH labels(n) AS labels +RETURN labels, count(*); + +// However, Bob is able to see all fields of the Patient records: + +RETURN "Finding patients" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + +// Bob cannot remove a patient that has been diagnosed, because he cannot see the diagnosis + +RETURN "Find a specific patient to try delete" AS `------------------------------------------------`; + +MATCH (x:Patient) WITH x.ssn as ssn SKIP 10 LIMIT 1 +MATCH (n:Patient) + WHERE n.ssn = ssn +RETURN n.ssn; + +// Uncomment the next section to test +//RETURN "Unable to delete a patient that is diagnosed" AS `------------------------------------------------`; + +//MATCH (x:Patient) WITH x.ssn as ssn SKIP 10 LIMIT 1 +//MATCH (n:Patient) +// WHERE n.ssn = ssn +//DETACH DELETE n; + +RETURN "Patient should still be there after attempt to delete it" AS `------------------------------------------------`; + +MATCH (x:Patient) WITH x.ssn as ssn SKIP 10 LIMIT 1 +MATCH (n:Patient) + WHERE n.ssn = ssn +RETURN n.ssn; + +// Bob can create new patients, and modify and delete them, as long as they are not yet connected (diagnosed) + +RETURN "Can create a new patient" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.ssn = 87654321 +DETACH DELETE n; + +CREATE (n:Patient { + ssn:87654321, + name: 'Another Patient', + email: 'another@example.com', + address: '1 secret way, downtown', + dateOfBirth: date('2001-01-20') +}) +RETURN n.name, n.dateOfBirth; + +RETURN "Can modify a patient" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.ssn = 87654321 +SET n.address = '2 streets down, uptown' +RETURN n.name, n.dateOfBirth, n.address; + +RETURN "Able to delete a patient that is un-diagnosed" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.ssn = 87654321 +DETACH DELETE n; + +RETURN "Should not find deleted patient" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.ssn = 87654321 +RETURN n.name, n.dateOfBirth, n.address; + + diff --git a/models/hospital/healthcare_queries_researcherB.cypher b/models/hospital/healthcare_queries_researcherB.cypher new file mode 100644 index 000000000..925957a2b --- /dev/null +++ b/models/hospital/healthcare_queries_researcherB.cypher @@ -0,0 +1,22 @@ +// +// The researcher is read-only and in addition cannot see any patient data +// + +// Charlie can read patient records but see very little + +RETURN "Finding patients, but not named, ssn or addresses" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + +// Charlie can perform statistical analysis + +RETURN "Finding diseases scored" AS `------------------------------------------------`; + +WITH datetime() - duration({years:25}) AS timeLimit +MATCH (n:Patient) +WHERE n.dateOfBirth > date(timeLimit) +MATCH (n)-[h:HAS]->(s:Symptom)-[o:OF]->(d:Disease) +WITH d.name AS disease, o.probability AS prob +RETURN disease, sum(prob) AS score ORDER BY score DESC LIMIT 10; diff --git a/models/hospital/healthcare_queries_researcherW.cypher b/models/hospital/healthcare_queries_researcherW.cypher new file mode 100644 index 000000000..232a97332 --- /dev/null +++ b/models/hospital/healthcare_queries_researcherW.cypher @@ -0,0 +1,22 @@ +// +// The researcher is read-only and in addition cannot see any patient data +// + +// Charlie can read patient records but see very little + +RETURN "Finding patients, but not names, ssn or addresses" AS `------------------------------------------------`; + +MATCH (n:Patient) + WHERE n.dateOfBirth < date('1972-06-12') +RETURN n.name, n.ssn, n.address, n.dateOfBirth; + +// Charlie can perform statistical analysis + +RETURN "Finding diseases scored" AS `------------------------------------------------`; + +WITH datetime() - duration({years:25}) AS timeLimit +MATCH (n:Patient) +WHERE n.dateOfBirth > date(timeLimit) +MATCH (n)-[h:HAS]->(s:Symptom)-[o:OF]->(d:Disease) +WITH d.name AS disease, o.probability AS prob +RETURN disease, sum(prob) AS score ORDER BY score DESC LIMIT 10; diff --git a/models/hospital/healthcare_queries_userManager.cypher b/models/hospital/healthcare_queries_userManager.cypher new file mode 100644 index 000000000..856655b6b --- /dev/null +++ b/models/hospital/healthcare_queries_userManager.cypher @@ -0,0 +1,12 @@ +// +// The user manager can create and assign users to roles +// + +DROP USER sally IF EXISTS; + +CREATE USER sally SET PASSWORD 'secret' CHANGE REQUIRED; +GRANT ROLE receptionist TO sally; +SHOW USER sally PRIVILEGES AS COMMANDS; + + + diff --git a/models/hospital/make_healthcare.cypher b/models/hospital/make_healthcare.cypher new file mode 100644 index 000000000..4d86955bc --- /dev/null +++ b/models/hospital/make_healthcare.cypher @@ -0,0 +1,39 @@ +// +// This script builds the tables of patients +// + + +// Delete previous data +MATCH (n:Patient) DETACH DELETE n; + +// Build new semi-random data for patients +WITH + ['Jack','Mary','Sally','Mark','Joe','Jane','Bob','Ally'] AS firstnames, + ['Anderson','Jackson','Svensson','Smith','Stone'] AS surnames, + ['mymail.com','example.com','other.org','net.net'] AS domains +UNWIND range(0,100) AS uid +WITH 1234567+uid AS ssn, + firstnames[uid%size(firstnames)] AS firstname, + surnames[uid%size(surnames)] AS surname, + domains[uid%size(domains)] AS domain +WITH ssn, firstname, surname, + tolower(firstname + '.' + surname + '@' + domain) AS email, + toInteger(1500000000000 * rand()) AS ts +MERGE (p:Patient {ssn:ssn}) +ON CREATE SET p.name = firstname + ' ' + surname, + p.email = email, + p.address = '1 secret way, downtown', + p.dateOfBirth = date(datetime({epochmillis:ts})) +RETURN count(p); + +// Build new semi-random data for patients' symptoms +MATCH (s:Symptom) WITH collect(s) as symptoms +WITH symptoms, size(symptoms) / 2 as maxsym, 1500000000000 AS base, 75477004177 AS diff +MATCH (p:Patient) +UNWIND range(0,maxsym) as symi +WITH p, symi, symptoms, toInteger(size(symptoms) * rand()) as si, rand()/2 + 0.5 AS prob, base + toInteger(diff * rand()) AS ts +WITH p, symptoms[si] AS s, prob, ts +MERGE (p)-[h:HAS]->(s) +ON CREATE SET h.date = date(datetime({epochmillis:ts})) +RETURN p.name, p.dateOfBirth, h.date, s.name; + diff --git a/models/hospital/make_healthcare_meta.cypher b/models/hospital/make_healthcare_meta.cypher new file mode 100644 index 000000000..27c528ca8 --- /dev/null +++ b/models/hospital/make_healthcare_meta.cypher @@ -0,0 +1,45 @@ +// +// This script builds the tables of diseases and symptoms +// + +// Delete previous data +MATCH (n:Symptom) DETACH DELETE n; +MATCH (n:Disease) DETACH DELETE n; + +// Build new semi-random data for symptoms +WITH ['Itchy','Scratchy','Sore','Swollen','Red','Inflamed','Angry','Sad','Pale','Dizzy'] AS symptoms +UNWIND symptoms AS symptom +MERGE (s:Symptom {name:symptom}) +ON CREATE SET s.description = 'Looks ' + toLower(symptom) +RETURN s.name, s.description; + +// Build new semi-random data for diseases +WITH + ['Argitis','Whatitis','Otheritis','Someitis','Placeboitis','Yellowitis'] AS diseases, + ['Chronic','Acute'] AS severity +UNWIND diseases AS disease +UNWIND severity as sev +MERGE (d:Disease {name:sev+' '+disease}) +ON CREATE SET d.description = sev + ' ' + toLower(disease) +RETURN d.name, d.description; + +MATCH (s:Symptom) WITH collect(s) as symptoms +WITH symptoms, size(symptoms) / 2 as maxsym +MATCH (d:Disease) +UNWIND range(0,maxsym) as symi +WITH d, symi, symptoms, toInteger(size(symptoms) * rand()) as si, rand()/2 + 0.5 AS prob +WITH d, symptoms[si] AS s, prob +MERGE (s)-[o:OF]->(d) +ON CREATE SET o.probability = prob +RETURN d.name, o.probability, s.name; + +// Ensure that the as yet non-existent types can be used + +CALL db.createRelationshipType('DIAGNOSIS'); +CALL db.createProperty('by'); +CALL db.createProperty('date'); +CALL db.createProperty('description'); +CALL db.createProperty('created_at'); +CALL db.createProperty('updated_at'); + + diff --git a/models/hospital/run_roles.sh b/models/hospital/run_roles.sh new file mode 100755 index 000000000..eabcc0552 --- /dev/null +++ b/models/hospital/run_roles.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +source healthcare_config.sh +USER_ROLES="bob.receptionist tina.itadmin charlie.researcherB charlie.researcherW alice.doctor daniel.broken daniel.nurse daniel.junior tina.userManager" + +#GRANT ROLE itadmin TO tina; +#GRANT ROLE researcherB TO charlie; +#GRANT ROLE doctor TO alice; +#GRANT ROLE receptionist TO bob; +#GRANT ROLE doctor, receptionist TO daniel; + +function revokeRoles +{ + u=$1 + for r in "${@:2}" + do + echo "REVOKE ROLE $r FROM $u;" + echo "REVOKE ROLE $r FROM $u;" | $CYPHER_SHELL $SY_CONNECT 2>/dev/null + done +} + +function grantRoles +{ + u=$1 + for r in "${@:2}" + do + echo "GRANT ROLE $r TO $u;" + echo "GRANT ROLE $r TO $u;" | $CYPHER_SHELL $SY_CONNECT 2>/dev/null + done +} + +function testUserRole +{ + user=$1 + role=$2 + echo -e "\nTesting '$user' as '$role'\n----------------------------------\n" + file="healthcare_queries_${role}.cypher" + if [ -f "$file" ] ; then + dbname=$DB_NAME + dbaddress=$DB_ADDRESS + if [ $role == "userManager" ] ; then + dbname="system" + dbaddress="$NEO4J_ADDRESS" + fi + if [ $role == "broken" ] ; then + revokeRoles $user doctor receptionist disableDiagnoses nurse + grantRoles $user doctor receptionist + elif [ $role == "junior" ] ; then + revokeRoles $user doctor receptionist disableDiagnoses nurse + grantRoles $user nurse disableDiagnoses + elif [ $role == "nurse" ] ; then + revokeRoles $user doctor receptionist disableDiagnoses nurse + grantRoles $user nurse + elif [ $role == "userManager" ] ; then + revokeRoles $user $role itadmin + grantRoles $user $role + elif [ $role == "itadmin" ] ; then + revokeRoles $user $role userManager + grantRoles $user $role + else + revokeRoles $user $role + grantRoles $user $role + fi + echo "SHOW POPULATED ROLES;" | $CYPHER_SHELL $SY_CONNECT + echo "SHOW USER $user PRIVILEGES AS COMMANDS;" | $CYPHER_SHELL --format verbose $SY_CONNECT + + USER_CONNECT="-u $user -p secret -a $dbaddress" + cat $file | sed -e "s/DATABASE healthcare/DATABASE $DB_NAME/" -e "s/GRAPH healthcare/GRAPH $DB_NAME/" | $CYPHER_SHELL --format verbose -d $dbname $USER_CONNECT + + echo "REVOKE ROLE $role FROM $user;" | $CYPHER_SHELL $SY_CONNECT 2>/dev/null + else + echo "No such file: '$file'" + fi + echo -e "\n" +} + +for userRole in $USER_ROLES +do + readarray -d . -t strarr <<< "${userRole}" + user="${strarr[0]}" + rolex="${strarr[1]}" + role="${rolex//[$'\n']}" + selected="" + if [[ -z "$@" ]] ; then + selected="all" + elif [[ "$@" == *"$role"* ]] ; then + echo "Selected role: $role" + selected=$role + fi + if [ -n "$selected" ] ; then + testUserRole $user $role + fi +done diff --git a/models/hospital/setup_healthcare.cypher b/models/hospital/setup_healthcare.cypher new file mode 100644 index 000000000..1ec48bfd6 --- /dev/null +++ b/models/hospital/setup_healthcare.cypher @@ -0,0 +1,18 @@ +DROP USER charlie IF EXISTS; +DROP USER alice IF EXISTS; +DROP USER daniel IF EXISTS; +DROP USER bob IF EXISTS; +DROP USER tina IF EXISTS; +CREATE USER charlie IF NOT EXISTS SET PASSWORD 'secretpass1' CHANGE NOT REQUIRED; +CREATE USER alice IF NOT EXISTS SET PASSWORD 'secretpass2' CHANGE NOT REQUIRED; +CREATE USER daniel IF NOT EXISTS SET PASSWORD 'secretpass3' CHANGE NOT REQUIRED; +CREATE USER bob IF NOT EXISTS SET PASSWORD 'secretpass4' CHANGE NOT REQUIRED; +CREATE USER tina IF NOT EXISTS SET PASSWORD 'secretpass5' CHANGE NOT REQUIRED; +SHOW DATABASES; +GRANT ROLE reader TO charlie; +GRANT ROLE editor TO alice; +GRANT ROLE editor TO daniel; +GRANT ROLE editor TO bob; +GRANT ROLE admin TO tina; +SHOW USERS; + diff --git a/models/hospital/setup_healthcare.sh b/models/hospital/setup_healthcare.sh new file mode 100755 index 000000000..706e3de60 --- /dev/null +++ b/models/hospital/setup_healthcare.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +source healthcare_config.sh + +#bin/neo4j-admin dbms set-initial-password $NEO4J_PASSWORD +#bin/neo4j start +#sleep 60 + +# Create the database + +echo -e "\nCreating the database $INDEXES_LABELS\n" +dbfile=/tmp/healthcare_database.txt +if [ "$DB_NAME" != "neo4j" ] ; then + echo "CREATE DATABASE $DB_NAME IF NOT EXISTS;" | $CYPHER_SHELL $SY_CONNECT + sleep 2 +fi +echo "SHOW DATABASES WHERE name = '$DB_NAME';" | $CYPHER_SHELL $SY_CONNECT > $dbfile + +function makeDetectedFile +{ + DB_ADDRESS=$1 + DB_CONNECT="-d $DB_NAME -u $NEO4J_USERNAME -p $NEO4J_PASSWORD -a $DB_ADDRESS" + echo "#!/bin/bash" > healthcare_detected.sh + echo "DB_ADDRESS=\"$DB_ADDRESS\"" >> healthcare_detected.sh + echo "DB_CONNECT=\"$DB_CONNECT\"" >> healthcare_detected.sh +} + +rm -f healthcare_detected.sh +if [ -n "$ENABLE_CLUSTERING" ] ; then + echo "Configuration uses clustering - searching for cluster leader for write commands" + cat $dbfile | grep leader >/dev/null + if [ "$?" = "0" ] ; then + echo "Found a leader for $DB_NAME" + DB_ADDRESS=`cat $dbfile | grep leader | awk -F'"' '{printf "bolt://%s\n",$4}'` + DB_CONNECT="-d $DB_NAME -u $NEO4J_USERNAME -p $NEO4J_PASSWORD -a $DB_ADDRESS" + makeDetectedFile $DB_ADDRESS + else + echo "Did not find a leader for $DB_NAME" + cat $dbfile + fi +else + makeDetectedFile $NEO4J_ADDRESS +fi +echo "Connecting to 'system' using: $SY_CONNECT" +echo "Connecting to '$DB_NAME' using: $DB_CONNECT" + +# Reconfigure indexes + +echo -e "\nCreating indexes for $INDEXES_LABELS\n" +for label in $INDEXES_LABELS +do + property="name" + index_name="${DB_NAME}_${label,,}_${property}" + new_index_definition="FOR (n:${label}) ON (n.${property})" + echo "Recreating index $index_name" + echo "DROP INDEX $index_name;" | $CYPHER_SHELL $DB_CONNECT 2>/dev/null + echo "CREATE INDEX $index_name $new_index_definition;" | $CYPHER_SHELL $DB_CONNECT +done +echo "SHOW INDEXES" | $CYPHER_SHELL $DB_CONNECT + +# Model with only built-in roles + +echo -e "\nCreating data with privileges based on built-in roles\n" + +cat setup_healthcare.cypher | $CYPHER_SHELL $SY_CONNECT +cat make_healthcare_meta.cypher | $CYPHER_SHELL $DB_CONNECT +cat make_healthcare.cypher | $CYPHER_SHELL $DB_CONNECT + +# Enhance model with fine-grained security + +echo -e "\nEnhancing security model with fine-grained privileges\n" + +cat setup_healthcare_privileges.cypher | sed -e "s/DATABASE healthcare/DATABASE $DB_NAME/" -e "s/GRAPH healthcare/GRAPH $DB_NAME/" | $CYPHER_SHELL --format verbose $SY_CONNECT diff --git a/models/hospital/setup_healthcare_privileges.cypher b/models/hospital/setup_healthcare_privileges.cypher new file mode 100644 index 000000000..4c727e6df --- /dev/null +++ b/models/hospital/setup_healthcare_privileges.cypher @@ -0,0 +1,139 @@ +// Remove previous coarse-grain roles + +REVOKE ROLE reader FROM charlie; +REVOKE ROLE editor FROM alice; +REVOKE ROLE editor FROM daniel; +REVOKE ROLE editor FROM bob; +REVOKE ROLE admin FROM tina; +SHOW USERS; + +// Create new roles for fine grained privileges + +DROP ROLE doctor IF EXISTS; +DROP ROLE nurse IF EXISTS; +DROP ROLE receptionist IF EXISTS; +DROP ROLE researcher IF EXISTS; +DROP ROLE researcherB IF EXISTS; +DROP ROLE researcherW IF EXISTS; +DROP ROLE disableDiagnoses IF EXISTS; +DROP ROLE itadmin IF EXISTS; +DROP ROLE userManager IF EXISTS; + +CREATE ROLE doctor IF NOT EXISTS; +CREATE ROLE nurse IF NOT EXISTS; +CREATE ROLE receptionist IF NOT EXISTS; +CREATE ROLE researcherB IF NOT EXISTS; +CREATE ROLE researcherW IF NOT EXISTS; +CREATE ROLE disableDiagnoses IF NOT EXISTS; +CREATE ROLE itadmin IF NOT EXISTS AS COPY OF admin; +CREATE ROLE userManager IF NOT EXISTS; +SHOW ROLES; +SHOW ROLE doctor PRIVILEGES AS COMMANDS; +SHOW ROLE nurse PRIVILEGES AS COMMANDS; +SHOW ROLE receptionist PRIVILEGES AS COMMANDS; +SHOW ROLE researcherB PRIVILEGES AS COMMANDS; +SHOW ROLE researcherW PRIVILEGES AS COMMANDS; +SHOW ROLE disableDiagnoses PRIVILEGES AS COMMANDS; +SHOW ROLE itadmin PRIVILEGES AS COMMANDS; +SHOW ROLE userManager PRIVILEGES AS COMMANDS; + +// Allow all users to access the new database + +GRANT ACCESS ON DATABASE healthcare TO PUBLIC; + +// Assign fine-grained privileges + +// Setup `itadmin` by blacklisting on top of copy of `admin` + +DENY READ {ssn} ON GRAPH healthcare NODES Patient TO itadmin; +DENY CREATE ON GRAPH healthcare RELATIONSHIPS DIAGNOSIS TO itadmin; + +// Assign researcher using denylisting + +// First grant read access to everything +GRANT MATCH {*} + ON GRAPH healthcare + TO researcherB; +// Then deny read on specific node properties +DENY READ {name, address, ssn} + ON GRAPH healthcare + NODES Patient + TO researcherB; +// And deny traversal of the doctors diagnosis +DENY TRAVERSE + ON GRAPH healthcare + RELATIONSHIPS DIAGNOSIS + TO researcherB; + +// Assign researcher using allowlisting + +// We allow the researcher to find all nodes +GRANT TRAVERSE + ON GRAPH healthcare + NODES * + TO researcherW; +// Now only allow the researcher to traverse specific relationships +GRANT TRAVERSE + ON GRAPH healthcare + RELATIONSHIPS HAS, OF + TO researcherW; +// Allow reading of all properties of medical metadata +GRANT READ {*} + ON GRAPH healthcare + NODES Symptom, Disease + TO researcherW; +// Allow reading of all properties of the disease-symptom relationship +GRANT READ {*} + ON GRAPH healthcare + RELATIONSHIPS OF + TO researcherW; +// Only allow reading dateOfBirth for research purposes +GRANT READ {dateOfBirth} + ON GRAPH healthcare + NODES Patient + TO researcherW; + +// Setup doctor + +GRANT TRAVERSE ON GRAPH healthcare TO doctor; +GRANT READ {*} ON GRAPH healthcare TO doctor; +GRANT WRITE ON GRAPH healthcare TO doctor; +DENY READ {address} ON GRAPH healthcare NODES Patient TO doctor; +DENY SET PROPERTY {address} ON GRAPH healthcare NODES Patient TO doctor; + +// Now the receptionist + +GRANT MATCH {*} ON GRAPH healthcare NODES Patient TO receptionist; +GRANT CREATE ON GRAPH healthcare NODES Patient TO receptionist; +GRANT DELETE ON GRAPH healthcare NODES Patient TO receptionist; +GRANT SET PROPERTY {*} ON GRAPH healthcare NODES Patient TO receptionist; +// set label is not required for creating nodes with that label +//GRANT SET LABEL Patient ON GRAPH healthcare TO receptionist; + +// Setup nurse + +GRANT TRAVERSE ON GRAPH healthcare TO nurse; +GRANT READ {*} ON GRAPH healthcare TO nurse; +GRANT WRITE ON GRAPH healthcare TO nurse; + +// Setup `disableDiagnoses` by blacklisting creation of the DIAGNOSIS relationship + +DENY CREATE ON GRAPH healthcare RELATIONSHIPS DIAGNOSIS TO disableDiagnoses; + +// Setup `userManager` with user and role management + +GRANT USER MANAGEMENT ON DBMS TO userManager; +GRANT ROLE MANAGEMENT ON DBMS TO userManager; +GRANT SHOW PRIVILEGE ON DBMS TO userManager; + +// Let's see the results + +SHOW ROLES; +SHOW ROLE doctor PRIVILEGES AS COMMANDS; +SHOW ROLE nurse PRIVILEGES AS COMMANDS; +SHOW ROLE receptionist PRIVILEGES AS COMMANDS; +SHOW ROLE researcherB PRIVILEGES AS COMMANDS; +SHOW ROLE researcherW PRIVILEGES AS COMMANDS; +SHOW ROLE itadmin PRIVILEGES AS COMMANDS; +SHOW ROLE userManager PRIVILEGES AS COMMANDS; + diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index 4d36ae8cd..dde23f590 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -2,8 +2,6 @@ * xref:introduction.adoc[] * xref:installation/index.adoc[] ** xref:installation/requirements.adoc[] -** xref:installation/neo4j-browser.adoc[] -** xref:installation/neo4j-desktop.adoc[] ** xref:installation/linux/index.adoc[] *** xref:installation/linux/debian.adoc[] *** xref:installation/linux/rpm.adoc[] @@ -11,25 +9,24 @@ *** xref:installation/linux/systemd.adoc[] ** xref:installation/osx.adoc[] ** xref:installation/windows.adoc[] +** xref:installation/neo4j-desktop.adoc[] * xref:cloud-deployments/index.adoc[] ** xref:cloud-deployments/neo4j-aws.adoc[] -** xref:cloud-deployments/neo4j-gcp/index.adoc[] -*** xref:cloud-deployments/neo4j-gcp/single-instance-vm.adoc[] -*** xref:cloud-deployments/neo4j-gcp/cluster-vm.adoc[] -*** xref:cloud-deployments/neo4j-gcp/automation-gcp.adoc[] -** xref:cloud-deployments/neo4j-azure/index.adoc[] -*** xref:cloud-deployments/neo4j-azure/single-instance-azure.adoc[] -*** xref:cloud-deployments/neo4j-azure/cluster-azure.adoc[] -*** xref:cloud-deployments/neo4j-azure/automation-azure.adoc[] +** xref:cloud-deployments/neo4j-gcp.adoc[] +** xref:cloud-deployments/neo4j-azure.adoc[] * xref:docker/index.adoc[] ** xref:docker/introduction.adoc[] +** xref:docker/mounting-volumes.adoc[] ** xref:docker/configuration.adoc[] +** xref:docker/plugins.adoc[] +** xref:docker/docker-compose-standalone.adoc[] ** xref:docker/clustering.adoc[] ** xref:docker/operations.adoc[] +** xref:docker/dump-load.adoc[] +** xref:docker/backup-restore.adoc[] ** xref:docker/security.adoc[] -** xref:docker/maintenance.adoc[] ** xref:docker/ref-settings.adoc[] * xref:kubernetes/index.adoc[] @@ -51,44 +48,101 @@ *** xref:kubernetes/quickstart-cluster/access-inside-k8s.adoc[] *** xref:kubernetes/quickstart-cluster/access-outside-k8s.adoc[] *** xref:kubernetes/quickstart-cluster/uninstall-cleanup.adoc[] -** xref:kubernetes/configuration.adoc[] +** xref:kubernetes/quickstart-analytics-cluster.adoc[] ** xref:kubernetes/persistent-volumes.adoc[] +** xref:kubernetes/configuration.adoc[] +** xref:kubernetes/security.adoc[] +** xref:kubernetes/authentication-authorization.adoc[] +** xref:kubernetes/plugins.adoc[] ** xref:kubernetes/accessing-neo4j.adoc[] -** xref:kubernetes/accessing-cluster.adoc[] +** xref:kubernetes/accessing-neo4j-ingress.adoc[] ** xref:kubernetes/import-data.adoc[] ** xref:kubernetes/monitoring.adoc[] -** xref:kubernetes/maintenance.adoc[] +** xref:kubernetes/operations/index.adoc[] +*** xref:kubernetes/operations/maintenance-mode.adoc[] +*** xref:kubernetes/operations/reset-password.adoc[] +*** xref:kubernetes/operations/dump-load.adoc[] +*** xref:kubernetes/operations/backup-restore.adoc[] +*** xref:kubernetes/operations/upgrade.adoc[] +*** xref:kubernetes/operations/migrate-from-labs.adoc[] +*** xref:kubernetes/operations/scaling.adoc[] +*** xref:kubernetes/operations/image-pull-secret.adoc[] +*** xref:kubernetes/operations/assign-neo4j-pods.adoc[] ** Deploy a multi-data center Neo4j cluster *** xref:kubernetes/multi-dc-cluster/aks.adoc[] ** xref:kubernetes/troubleshooting.adoc[] * xref:configuration/index.adoc[] ** xref:configuration/neo4j-conf.adoc[] +** xref:configuration/command-expansion.adoc[] ** xref:configuration/file-locations.adoc[] //** xref:configuration/network-architecture.adoc[] ** xref:configuration/ports.adoc[] ** xref:configuration/connectors.adoc[] ** xref:configuration/set-initial-password.adoc[] -** xref:configuration/password-and-user-recovery.adoc[] +** xref:configuration/plugins.adoc[Plugins] ** xref:configuration/dynamic-settings.adoc[] -** xref:configuration/transaction-logs.adoc[] - -* xref:manage-databases/index.adoc[] -** xref:manage-databases/introduction.adoc[] -** xref:manage-databases/configuration.adoc[] -** xref:manage-databases/queries.adoc[] -** xref:manage-databases/errors.adoc[] -** xref:manage-databases/remote-alias.adoc[] -** xref:composite-databases/index.adoc[] -*** xref:composite-databases/introduction.adoc[] -*** xref:composite-databases/queries.adoc[] -*** xref:composite-databases/sharding-with-copy.adoc[] -*** xref:composite-databases/considerations.adoc[] +** xref:configuration/configuration-settings.adoc[] +*** xref:configuration/configuration-settings.adoc#_checkpoint_settings[Checkpoint settings] +*** xref:configuration/configuration-settings.adoc#_cloud_storage_integration_settings[Cloud storage integration settings] +*** xref:configuration/configuration-settings.adoc#_cluster_settings[Cluster settings] +*** xref:configuration/configuration-settings.adoc#_connection_settings[Connection settings] +*** xref:configuration/configuration-settings.adoc#_cypher_settings[Cypher settings] +*** xref:configuration/configuration-settings.adoc#_database_settings[Database settings] +*** xref:configuration/configuration-settings.adoc#_dbms_settings[DBMS settings] +*** xref:configuration/configuration-settings.adoc#_import_settings[Import settings] +*** xref:configuration/configuration-settings.adoc#_index_settings[Index settings] +*** xref:configuration/configuration-settings.adoc#_logging_settings[Logging settings] +*** xref:configuration/configuration-settings.adoc#_memory_settings[Memory settings] +*** xref:configuration/configuration-settings.adoc#_metrics_settings[Metrics settings] +*** xref:configuration/configuration-settings.adoc#_neo4j_browser_and_client_settings[Neo4j Browser and client settings] +*** xref:configuration/configuration-settings.adoc#_kubernetes_settings[Kubernetes settings] +*** xref:configuration/configuration-settings.adoc#_security_settings[Security settings] +*** xref:configuration/configuration-settings.adoc#_server_directories_settings[Server directories settings] +*** xref:configuration/configuration-settings.adoc#_server_settings[Server settings] +*** xref:configuration/configuration-settings.adoc#_transaction_settings[Transaction settings] +*** xref:configuration/configuration-settings.adoc#_transaction_log_settings[Transaction log settings] + +* xref:database-administration/index.adoc[] +** xref:database-administration/syntax.adoc[] +** Standard databases +*** xref:database-administration/standard-databases/naming-databases.adoc[] +*** xref:database-administration/standard-databases/create-databases.adoc[] +*** xref:database-administration/standard-databases/seed-from-uri.adoc[] +*** xref:database-administration/standard-databases/listing-databases.adoc[] +*** xref:database-administration/standard-databases/alter-databases.adoc[] +*** xref:database-administration/standard-databases/recreate-database.adoc[] +*** xref:database-administration/standard-databases/delete-databases.adoc[] +*** xref:database-administration/standard-databases/wait-options.adoc[] +*** xref:database-administration/standard-databases/configuration-parameters.adoc[] +*** xref:database-administration/standard-databases/errors.adoc[] +** Database aliases +*** xref:database-administration/aliases/naming-aliases.adoc[] +*** xref:database-administration/aliases/manage-aliases-standard-databases.adoc[] +*** xref:database-administration/aliases/manage-aliases-composite-databases.adoc[] +*** xref:database-administration/aliases/remote-database-alias-configuration.adoc[] +** Composite databases +*** xref:database-administration/composite-databases/concepts.adoc[] +*** xref:database-administration/composite-databases/create-composite-databases.adoc[] +*** xref:database-administration/composite-databases/list-composite-databases.adoc[] +*** xref:database-administration/composite-databases/delete-composite-databases.adoc[] +*** xref:database-administration/composite-databases/querying-composite-databases.adoc[] +*** xref:database-administration/composite-databases/sharding-with-copy.adoc[] +** xref:database-administration/routing-decisions.adoc[] + +* xref:database-internals/index.adoc[] +** xref:database-internals/transaction-management.adoc[] +** xref:database-internals/concurrent-data-access.adoc[] +** xref:database-internals/transaction-logs.adoc[] +** xref:database-internals/checkpointing.adoc[] +** xref:database-internals/store-formats.adoc[] * xref:clustering/index.adoc[] ** xref:clustering/introduction.adoc[] -** Set up a cluster +** Setting up a cluster *** xref:clustering/setup/deploy.adoc[] +*** xref:clustering/setup/analytics-cluster.adoc[] +*** xref:clustering/setup/single-to-cluster.adoc[] *** xref:clustering/setup/discovery.adoc[] *** xref:clustering/setup/routing.adoc[] *** xref:clustering/setup/encryption.adoc[] @@ -97,32 +151,54 @@ ** Monitoring *** xref:clustering/monitoring/show-servers-monitoring.adoc[] *** xref:clustering/monitoring/show-databases-monitoring.adoc[] +*** xref:clustering/monitoring/endpoints.adoc[] +*** xref:clustering/monitoring/status-check.adoc[] ** xref:clustering/disaster-recovery.adoc[] //** xref:clustering/internals.adoc[] ** xref:clustering/settings.adoc[] +** xref:clustering/server-syntax.adoc[] +** xref:clustering/clustering-advanced/index.adoc[] +*** xref:clustering/clustering-advanced/default-database.adoc[] +*** xref:clustering/clustering-advanced/multi-data-center-routing.adoc[] +*** xref:clustering/clustering-advanced/reconciler.adoc[] +** xref:clustering/glossary.adoc[] * xref:backup-restore/index.adoc[] ** xref:backup-restore/planning.adoc[] ** xref:backup-restore/modes.adoc[] ** xref:backup-restore/online-backup.adoc[] ** xref:backup-restore/aggregate.adoc[] +** xref:backup-restore/inspect.adoc[] ** xref:backup-restore/restore-backup.adoc[] ** xref:backup-restore/offline-backup.adoc[] ** xref:backup-restore/restore-dump.adoc[] ** xref:backup-restore/copy-database.adoc[] * xref:authentication-authorization/index.adoc[] -** xref:authentication-authorization/introduction.adoc[] +** xref:authentication-authorization/manage-users.adoc[] +** xref:authentication-authorization/manage-roles.adoc[] +** xref:authentication-authorization/password-and-user-recovery.adoc[] +** Manage privileges +*** xref:authentication-authorization/manage-privileges.adoc[] +*** xref:authentication-authorization/privileges-reads.adoc[] +*** xref:authentication-authorization/property-based-access-control.adoc[] +*** xref:authentication-authorization/privileges-writes.adoc[] +*** xref:authentication-authorization/database-administration.adoc[] +*** xref:authentication-authorization/dbms-administration.adoc[] +*** xref:authentication-authorization/load-privileges.adoc[] +*** xref:authentication-authorization/limitations.adoc[] +*** xref:authentication-authorization/manage-execute-permissions.adoc[] ** xref:authentication-authorization/built-in-roles.adoc[] -** xref:authentication-authorization/access-control.adoc[] -** xref:authentication-authorization/ldap-integration.adoc[] -** xref:authentication-authorization/sso-integration.adoc[] -** xref:authentication-authorization/manage-execute-permissions.adoc[] -** xref:authentication-authorization/terminology.adoc[] +** xref:authentication-authorization/immutable-roles-privileges.adoc[] +** Integration with auth systems +*** xref:authentication-authorization/auth-providers.adoc[] +*** xref:authentication-authorization/ldap-integration.adoc[] +*** xref:authentication-authorization/sso-integration.adoc[] * xref:security/index.adoc[] ** xref:security/securing-extensions.adoc[] ** xref:security/ssl-framework.adoc[] +*** xref:security/ssl-fips-compatibility.adoc[] ** xref:security/browser.adoc[] ** xref:security/checklist.adoc[] @@ -144,7 +220,6 @@ *** xref:monitoring/metrics/expose.adoc[] *** xref:monitoring/metrics/reference.adoc[] ** xref:monitoring/query-management.adoc[] -** xref:monitoring/transaction-management.adoc[] ** xref:monitoring/connection-management.adoc[] ** xref:monitoring/background-jobs.adoc[] // ** xref:monitoring/cluster/index.adoc[] @@ -159,23 +234,22 @@ *** xref:tools/neo4j-admin/neo4j-admin-memrec.adoc[] *** xref:tools/neo4j-admin/neo4j-admin-import.adoc[] *** xref:tools/neo4j-admin/unbind.adoc[] -*** xref:tools/neo4j-admin/push-to-cloud.adoc[] +*** xref:tools/neo4j-admin/upload-to-aura.adoc[] *** xref:tools/neo4j-admin/migrate-database.adoc[] *** xref:tools/neo4j-admin/migrate-configuration.adoc[] +*** xref:tools/neo4j-admin/validate-config.adoc[] ** xref:tools/cypher-shell.adoc[] -* Appendix -** xref:reference/index.adoc[] -*** xref:reference/configuration-settings.adoc[] -*** xref:reference/procedures.adoc[] - -** xref:tutorial/index.adoc[] -//*** xref:tutorial/local-causal-cluster.adoc[] -//*** xref:tutorial/causal-backup-restore-db.adoc[] -*** xref:tutorial/neo4j-admin-import.adoc[] -*** xref:tutorial/tutorial-composite-database.adoc[] -*** xref:tutorial/tutorial-sso-configuration.adoc[] -*** xref:tutorial/tutorial-immutable-privileges.adoc[] +* xref:procedures.adoc[] + +* xref:tutorial/index.adoc[] +//** xref:tutorial/local-causal-cluster.adoc[] +//** xref:tutorial/causal-backup-restore-db.adoc[] +** xref:tutorial/neo4j-admin-import.adoc[] +** xref:tutorial/tutorial-composite-database.adoc[] +** xref:tutorial/access-control.adoc[] +** xref:tutorial/tutorial-sso-configuration.adoc[] +** xref:tutorial/tutorial-clustering-docker.adoc[] // ** xref:clustering-advanced/index.adoc[] // *** xref:clustering-advanced/lifecycle.adoc[] diff --git a/modules/ROOT/images/az-neo4j-service.png b/modules/ROOT/images/az-neo4j-service.png new file mode 100644 index 000000000..38b841012 Binary files /dev/null and b/modules/ROOT/images/az-neo4j-service.png differ diff --git a/modules/ROOT/images/az-neo4j-url.png b/modules/ROOT/images/az-neo4j-url.png new file mode 100644 index 000000000..bc7cd93dc Binary files /dev/null and b/modules/ROOT/images/az-neo4j-url.png differ diff --git a/modules/ROOT/images/cluster-sysinfo.png b/modules/ROOT/images/cluster-sysinfo.png new file mode 100644 index 000000000..d453d86ef Binary files /dev/null and b/modules/ROOT/images/cluster-sysinfo.png differ diff --git a/modules/ROOT/images/discovery-service/in-place-1-v1-over-v2.png b/modules/ROOT/images/discovery-service/in-place-1-v1-over-v2.png new file mode 100644 index 000000000..e2b90a3e8 Binary files /dev/null and b/modules/ROOT/images/discovery-service/in-place-1-v1-over-v2.png differ diff --git a/modules/ROOT/images/discovery-service/in-place-1-v2-over-v1.png b/modules/ROOT/images/discovery-service/in-place-1-v2-over-v1.png new file mode 100644 index 000000000..c83995385 Binary files /dev/null and b/modules/ROOT/images/discovery-service/in-place-1-v2-over-v1.png differ diff --git a/modules/ROOT/images/discovery-service/in-place-123-v2-only.png b/modules/ROOT/images/discovery-service/in-place-123-v2-only.png new file mode 100644 index 000000000..6a20dd0a2 Binary files /dev/null and b/modules/ROOT/images/discovery-service/in-place-123-v2-only.png differ diff --git a/modules/ROOT/images/discovery-service/in-place-23-v1-over-v2.png b/modules/ROOT/images/discovery-service/in-place-23-v1-over-v2.png new file mode 100644 index 000000000..99a2a00e7 Binary files /dev/null and b/modules/ROOT/images/discovery-service/in-place-23-v1-over-v2.png differ diff --git a/modules/ROOT/images/discovery-service/in-place-23-v2-over-v1.png b/modules/ROOT/images/discovery-service/in-place-23-v2-over-v1.png new file mode 100644 index 000000000..c5519125d Binary files /dev/null and b/modules/ROOT/images/discovery-service/in-place-23-v2-over-v1.png differ diff --git a/modules/ROOT/images/discovery-service/v1-only.png b/modules/ROOT/images/discovery-service/v1-only.png new file mode 100644 index 000000000..e1dca0f4e Binary files /dev/null and b/modules/ROOT/images/discovery-service/v1-only.png differ diff --git a/modules/ROOT/images/discovery-service/v1_over_v2.png b/modules/ROOT/images/discovery-service/v1_over_v2.png new file mode 100644 index 000000000..7ff1b7a4e Binary files /dev/null and b/modules/ROOT/images/discovery-service/v1_over_v2.png differ diff --git a/modules/ROOT/images/discovery-service/v2_only.png b/modules/ROOT/images/discovery-service/v2_only.png new file mode 100644 index 000000000..b4707667d Binary files /dev/null and b/modules/ROOT/images/discovery-service/v2_only.png differ diff --git a/modules/ROOT/images/discovery-service/v2_over_v1.png b/modules/ROOT/images/discovery-service/v2_over_v1.png new file mode 100644 index 000000000..f895be98f Binary files /dev/null and b/modules/ROOT/images/discovery-service/v2_over_v1.png differ diff --git a/modules/ROOT/images/federation-sharding.png b/modules/ROOT/images/federation-sharding.png new file mode 100644 index 000000000..a34e6af96 Binary files /dev/null and b/modules/ROOT/images/federation-sharding.png differ diff --git a/modules/ROOT/images/pipeline-of-strategies.svg b/modules/ROOT/images/pipeline-of-strategies.svg index 6f0280626..7af1edd5a 100644 --- a/modules/ROOT/images/pipeline-of-strategies.svg +++ b/modules/ROOT/images/pipeline-of-strategies.svg @@ -13,14 +13,14 @@ connect-randomly-to- - server-group + server-tags typically-connect-to-random- - read-replica + secondary - connect-to-random-core-server + connect-to-random-primary-server diff --git a/modules/ROOT/images/privileges_grant_and_deny_syntax.svg b/modules/ROOT/images/privileges_grant_and_deny_syntax.svg new file mode 100644 index 000000000..be24fdde9 --- /dev/null +++ b/modules/ROOT/images/privileges_grant_and_deny_syntax.svg @@ -0,0 +1 @@ + diff --git a/modules/ROOT/images/privileges_grant_and_deny_syntax_database_privileges.svg b/modules/ROOT/images/privileges_grant_and_deny_syntax_database_privileges.svg new file mode 100644 index 000000000..4e0babc35 --- /dev/null +++ b/modules/ROOT/images/privileges_grant_and_deny_syntax_database_privileges.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/privileges_grant_and_deny_syntax_dbms_privileges.svg b/modules/ROOT/images/privileges_grant_and_deny_syntax_dbms_privileges.svg new file mode 100644 index 000000000..3d08de6ec --- /dev/null +++ b/modules/ROOT/images/privileges_grant_and_deny_syntax_dbms_privileges.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/privileges_grant_and_deny_syntax_load_privileges.svg b/modules/ROOT/images/privileges_grant_and_deny_syntax_load_privileges.svg new file mode 100644 index 000000000..b3cdea419 --- /dev/null +++ b/modules/ROOT/images/privileges_grant_and_deny_syntax_load_privileges.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/privileges_hierarchy.svg b/modules/ROOT/images/privileges_hierarchy.svg new file mode 100644 index 000000000..ce7ef40b1 --- /dev/null +++ b/modules/ROOT/images/privileges_hierarchy.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/modules/ROOT/images/privileges_hierarchy_database.svg b/modules/ROOT/images/privileges_hierarchy_database.svg new file mode 100644 index 000000000..0ccfd067d --- /dev/null +++ b/modules/ROOT/images/privileges_hierarchy_database.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/modules/ROOT/images/privileges_hierarchy_dbms.svg b/modules/ROOT/images/privileges_hierarchy_dbms.svg new file mode 100644 index 000000000..77c37a377 --- /dev/null +++ b/modules/ROOT/images/privileges_hierarchy_dbms.svg @@ -0,0 +1,750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/privileges_on_graph_syntax.svg b/modules/ROOT/images/privileges_on_graph_syntax.svg new file mode 100644 index 000000000..570896e2b --- /dev/null +++ b/modules/ROOT/images/privileges_on_graph_syntax.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/reverse-proxy.svg b/modules/ROOT/images/reverse-proxy.svg new file mode 100644 index 000000000..ae459b6c5 --- /dev/null +++ b/modules/ROOT/images/reverse-proxy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/ROOT/images/routing-decisions.svg b/modules/ROOT/images/routing-decisions.svg index eb62ab714..ade34e97a 100644 --- a/modules/ROOT/images/routing-decisions.svg +++ b/modules/ROOT/images/routing-decisions.svg @@ -1,12 +1,118 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/server-states3.png b/modules/ROOT/images/server-states3.png new file mode 100644 index 000000000..4a3984c1a Binary files /dev/null and b/modules/ROOT/images/server-states3.png differ diff --git a/modules/ROOT/images/server-states4.png b/modules/ROOT/images/server-states4.png new file mode 100644 index 000000000..508de1bdd Binary files /dev/null and b/modules/ROOT/images/server-states4.png differ diff --git a/modules/ROOT/images/sso-configuration-tutorials/azure-id.svg b/modules/ROOT/images/sso-configuration-tutorials/azure-id.svg new file mode 100644 index 000000000..d291b8143 --- /dev/null +++ b/modules/ROOT/images/sso-configuration-tutorials/azure-id.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/sso-configuration-tutorials/okta-claims.svg b/modules/ROOT/images/sso-configuration-tutorials/okta-claims.svg new file mode 100644 index 000000000..ff6fe9765 --- /dev/null +++ b/modules/ROOT/images/sso-configuration-tutorials/okta-claims.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/modules/ROOT/images/sso-configuration-tutorials/okta-sign-on-tab.svg b/modules/ROOT/images/sso-configuration-tutorials/okta-sign-on-tab.svg new file mode 100644 index 000000000..44d578d8c --- /dev/null +++ b/modules/ROOT/images/sso-configuration-tutorials/okta-sign-on-tab.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/modules/ROOT/pages/authentication-authorization/auth-providers.adoc b/modules/ROOT/pages/authentication-authorization/auth-providers.adoc new file mode 100644 index 000000000..ca0318d8a --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/auth-providers.adoc @@ -0,0 +1,69 @@ +:description: This section explains how to use Cypher to manage authentication and authorization at the user level using Cypher. +:page-role: enterprise-edition new-5.24 + +[[access-control-auth-providers]] += User auth providers + +Authentication and authorization can be controlled on a user level using Cypher by setting auth providers on users. + +To use auth providers, you need to set the xref:configuration/configuration-settings.adoc#config_dbms.security.require_local_user[`dbms.security.require_local_user`] configuration setting to `true`. +This setting mandates that users with the relevant auth provider attached to them must exist in the database before they can authenticate and authorize with that auth provider. + +User auth providers allow you to link externally-defined users (e.g., in a third-party ID provider like OIDC or LDAP) to the Neo4j internal user model. +The internal model can define roles (authorization), `SUSPENDED` status, `HOME DATABASE`, and metadata such as the unique displayed name of the user. +For consistency, you can also define `native` (password-based) auth using the auth provider syntax, including native-only users (i.e., users who can only authenticate with a password). + +== Use cases + +User auth providers can be used for a variety of use cases, including: + +* Provisioning different auth providers (including native username/password auth) for different users. +* Setting an arbitrary easy username for a user while using an external unique identifier (like `sub` for OIDC auths, which itself is not a user-friendly value). +* Setting `HOME DATABASE` for externally authenticated users. +* Setting `SUSPENDED` status for an externally authenticated user. +* Using native authorization to manage roles for externally authenticated users. +* Retaining full control of which users can authenticate from within the database. + +== How it works + +When a user authenticates, their identifying attributes are checked against the relevant property of the auth providers in the database. +If there is a match, then the user is linked to the Neo4j user and authorized according to the DBMS security configuration settings that match the name of the matching auth provider. + +How the matching lookup is done depends on the type of provider. +For example: + +* For an OIDC provider, the claim configured by xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.claims.username[`dbms.security.oidc.mysso.claims.username`] (default `sub`) is taken from the token and is used to look up an auth provider whose `ID` and `provider` properties match the `sub` and provider respectively of the OIDC provider. +* For an LDAP provider, the `dn` is used to look up an auth provider with a `provider` property of `ldap` and an `ID` property that matches the supplied `dn`. +* For the `native` (username/password) provider, the supplied username itself is used to look up the auth provider. + +== Enabling user auth providers mode + +To enable user auth providers mode, set the configuration setting xref:configuration/configuration-settings.adoc#config_dbms.security.require_local_user[`dbms.security.require_local_user`] to `true`. +This setting mandates that users with the relevant auth provider attached to them must exist in the database before they can authenticate and authorize with that auth provider. + +When the user authenticates, Neo4j searches for a user with a matching authentication provider. +If a match is found, the user can log in and be authorized successfully. + +== Migrating to auth providers mode + +If you have existing users in the database and want to migrate to auth providers mode, you can use the `ALTER USER ... SET AUTH` command to attach an auth provider to each of them. +Until you change `dbms.security.require_local_user` to `true`, this will not impact the users' ability to authenticate and authorize as they always have done. + +Once the process of adding auth providers to your users finishes, you can set `dbms.security.require_local_user` to `true` and restart the DBMS to complete the migration. +After this time, only users with a corresponding auth provider in the database will be able to authenticate and authorize. + +[NOTE] +==== +Existing users created using the original `CREATE USER ... SET PASSWORD` command implicitly have the native (username/password) auth provider, so you do not need to add it explicitly using `SET AUTH`. + +To verify which auth providers are attached to a user, use the xref:authentication-authorization/manage-users.adoc#access-control-list-users[`SHOW USERS WITH AUTH`] command. +==== + +== Examples + +For examples of how to use auth providers with different authentication providers, see the following sections: + +- xref:authentication-authorization/sso-integration.adoc#auth-sso-auth-providers[Configure SSO at the user level using auth providers] +- xref:authentication-authorization/manage-users.adoc#access-control-create-users[Creating users] +- xref:authentication-authorization/ldap-integration.adoc#auth-ldap-auth-providers[Configure authentication/authorization at the user level using LDAP as an auth provider] + diff --git a/modules/ROOT/pages/authentication-authorization/built-in-roles.adoc b/modules/ROOT/pages/authentication-authorization/built-in-roles.adoc index c6d2ea8e2..a69cf63ac 100644 --- a/modules/ROOT/pages/authentication-authorization/built-in-roles.adoc +++ b/modules/ROOT/pages/authentication-authorization/built-in-roles.adoc @@ -1,68 +1,77 @@ -[role=enterprise-edition] [[auth-built-in-roles]] -= Built-in roles -:description: This page describes the roles that come pre-defined with Neo4j. += Built-in roles and privileges +:description: The default privileges of the built-in roles in Neo4j and how to recreate them if needed. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated //Check Mark :check-mark: icon:check[] -Neo4j provides built-in roles with default privileges. The built-in roles and the default privileges are: +== Introduction + +Neo4j provides a set of built-in roles that can be used to control access to the database. +The `PUBLIC` role is the default role for all users. +It does not give any rights or capabilities regarding the data, not even read privileges. +The rest of the built-in roles are hierarchical, with the `reader` role at the bottom and the `admin` role at the top with all privileges. + +A user may have more than one assigned role, and the union of these determines what action(s) on the data may be undertaken by the user. +For instance, a user assigned to the `reader` role can execute procedures, because all users are also assigned to the `PUBLIC` role, which enables that capability. + +The built-in roles have the following default privileges: [.compact] -`PUBLIC`:: +<>:: * Access to the home database. -* Allows executing procedures with the users own privileges. -* Allows executing user-defined functions with the users own privileges. -`reader`:: +* Execute procedures with the users' own privileges. +* Execute user-defined functions with the users' own privileges. +* Load data. +<>:: * Access to all databases. * Traverse and read on the data graph (all nodes, relationships, properties). * Show indexes and constraints along with any other future schema constructs. -`editor`:: +<>:: * Access to all databases. * Traverse, read, and write on the data graph. -* Write access limited to creating and changing *existing* property keys, node labels, and relationship types of the graph. +* Write access, limited to creating and changing *existing* property keys, node labels, and relationship types of the graph. In other words, the `editor` role cannot add to the schema but can only make changes to already existing objects. * Show indexes and constraints along with any other future schema constructs. -`publisher`:: +<>:: * Access to all databases. * Traverse, read, and write on the data graph. * Show indexes and constraints along with any other future schema constructs. -`architect`:: +<>:: * Access to all databases. * Traverse, read, and write on the data graph. * Create/drop/show indexes and constraints along with any other future schema constructs. -`admin`:: +<>:: * Access to all databases. * Traverse, read, and write on the data graph. +* Load data. * Create/drop/show indexes and constraints along with any other future schema constructs. -* Allows executing procedures with the users own privileges or boosted privileges. -* Allows executing admin procedures. -* Allows executing user-defined functions with the users own privileges or boosted privileges. +* Execute procedures using boosted privileges. +* Execute admin procedures. +* Execute user-defined functions using boosted privileges. * View/terminate queries. * Manage databases, users, roles, and privileges. -All users will be assigned the `PUBLIC` role, which by default does not give any rights or capabilities regarding the data, not even read privileges. -A user may have more than one assigned role, and the union of these determine what action(s) on the data may be undertaken by the user. -For instance, a user assigned to the `reader` role will be able to execute procedures because all users are also -assigned to the `PUBLIC` role, which enables that capability. - When an administrator suspends or deletes another user, the following rules apply: * Administrators can suspend or delete any other user (including other administrators), but not themselves. -* The user will no longer be able to log back in (until re-activated by an administrator if suspended). -* There is no need to remove assigned roles from a user prior to deleting the user. +* When suspended, the user is no longer able to log back in until re-activated by an administrator. +* There is no need to remove assigned roles from a user before deleting the user. [NOTE] -- -Deleting a user will not automatically terminate associated connections, sessions, transactions, or queries. +Deleting a user does not automatically terminate associated connections, sessions, transactions, or queries. -- -The set of actions on the data and database prescribed by each role are described below. -The subset of the functionality which is available with Community Edition is also included: + +Neo4j provides the following built-in roles with default privileges and capabilities. +The subset of the functionality that is available with Community Edition is also included. +All of the commands require that the user executing the commands has the rights to do so. [[auth-built-in-roles-overview]] -.Native roles overview +.Built-in roles capabilities [options="header" cols="16d,^12a,^12a,^12a,^12a,^12a,^12a,^12a"] |=== | Action @@ -380,6 +389,16 @@ The subset of the functionality which is available with Community Edition is als | | {check-mark} +| Load data +| +| +| +| +| {check-mark} +| {check-mark} +| {check-mark} + + | Execute procedures | | @@ -407,8 +426,7 @@ The subset of the functionality which is available with Community Edition is als | | {check-mark} -| Dynamically change configuration (see xref:configuration/dynamic-settings.adoc[Dynamic settings]) -| +| Dynamically change configuration footnote:[For more information, see xref:configuration/dynamic-settings.adoc[Update dynamic settings]]| | | | @@ -417,5 +435,497 @@ The subset of the functionality which is available with Community Edition is als | |=== -More information about the built-in roles and their privileges can be found in -link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/built-in-roles[Neo4j Cypher Manual]. + +[[access-control-built-in-roles-public]] +== The `PUBLIC` role + +All users are granted the `PUBLIC` role, and it can not be revoked or dropped. +By default, it gives access to the default database and allows loading data, executing all procedures and user-defined functions. + +[IMPORTANT] +==== +The `PUBLIC` role cannot be dropped or revoked from any user, but the specific privileges for the role can be modified. +In contrast to the `PUBLIC` role, the other built-in roles can be granted, revoked, dropped, and re-created. +==== + +[[access-control-built-in-roles-public-list]] +=== Listing `PUBLIC` role privileges + +[source, cypher, role=noplay] +---- +SHOW ROLE PUBLIC PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON HOME DATABASE TO `PUBLIC`" +|"GRANT EXECUTE FUNCTION * ON DBMS TO `PUBLIC`" +|"GRANT EXECUTE PROCEDURE * ON DBMS TO `PUBLIC`" +|"GRANT LOAD ON ALL DATA TO `PUBLIC`" +a|Rows: 4 +|=== + + +[[access-control-built-in-roles-public-recreate]] +=== Recreating the `PUBLIC` role + +The `PUBLIC` role can not be dropped and thus there is no need to recreate the role itself. +To restore the role to its original capabilities, two steps are needed. + +First, all `GRANT` or `DENY` privileges on this role should be revoked (see output of `SHOW ROLE PUBLIC PRIVILEGES AS REVOKE COMMANDS` on what to revoke). +Secondly, run these queries: + +[source, cypher, role=noplay] +---- +GRANT ACCESS ON HOME DATABASE TO PUBLIC +---- + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURES * ON DBMS TO PUBLIC +---- + +[source, cypher, role=noplay] +---- +GRANT EXECUTE USER DEFINED FUNCTIONS * ON DBMS TO PUBLIC +---- + +[source, cypher, role=noplay] +---- +GRANT LOAD ON ALL DATA TO PUBLIC +---- + +The resulting `PUBLIC` role now has the same privileges as the original built-in `PUBLIC` role. + + +[[access-control-built-in-roles-reader]] +== The `reader` role + +The `reader` role can perform read-only queries on all graphs except for the `system` database. + + +[[access-control-built-in-roles-reader-list]] +=== Listing `reader` role privileges + +[source, cypher, role=noplay] +---- +SHOW ROLE reader PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON DATABASE * TO `reader`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `reader`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `reader`" +|"GRANT SHOW CONSTRAINT ON DATABASE * TO `reader`" +|"GRANT SHOW INDEX ON DATABASE * TO `reader`" +a|Rows: 5 +|=== + + +[[access-control-built-in-roles-reader-recreate]] +=== Recreating the `reader` role + +//// +[source, cypher, role=test-setup] +---- +DROP ROLE reader; +---- +//// + +To restore the role to its original capabilities two steps are needed. +First, execute `DROP ROLE reader`. +Secondly, run these queries: + +[source, cypher, role=noplay] +---- +CREATE ROLE reader +---- + +[source, cypher, role=noplay] +---- +GRANT ACCESS ON DATABASE * TO reader +---- + +[source, cypher, role=noplay] +---- +GRANT MATCH {*} ON GRAPH * TO reader +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW CONSTRAINT ON DATABASE * TO reader +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW INDEX ON DATABASE * TO reader +---- + +The resulting `reader` role now has the same privileges as the original built-in `reader` role. + + +[[access-control-built-in-roles-editor]] +== The `editor` role + +The `editor` role can perform read and write operations on all graphs except for the `system` database, but it cannot create new labels, property keys or relationship types. + +[[access-control-built-in-roles-editor-list]] +=== Listing `editor` role privileges + +[source, cypher, role=noplay] +---- +SHOW ROLE editor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON DATABASE * TO `editor`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `editor`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `editor`" +|"GRANT SHOW CONSTRAINT ON DATABASE * TO `editor`" +|"GRANT SHOW INDEX ON DATABASE * TO `editor`" +|"GRANT WRITE ON GRAPH * TO `editor`" +a|Rows: 6 +|=== + + +[[access-control-built-in-roles-editor-recreate]] +=== Recreating the `editor` role + +//// +[source, cypher, role=test-setup] +---- +DROP ROLE editor; +---- +//// + +To restore the role to its original capabilities two steps are needed. +First, execute `DROP ROLE editor`. +Secondly, run these queries: + +[source, cypher, role=noplay] +---- +CREATE ROLE editor +---- + +[source, cypher, role=noplay] +---- +GRANT ACCESS ON DATABASE * TO editor +---- + +[source, cypher, role=noplay] +---- +GRANT MATCH {*} ON GRAPH * TO editor +---- + +[source, cypher, role=noplay] +---- +GRANT WRITE ON GRAPH * TO editor +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW CONSTRAINT ON DATABASE * TO editor +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW INDEX ON DATABASE * TO editor +---- + +The resulting `editor` role now has the same privileges as the original built-in `editor` role. + + +[[access-control-built-in-roles-publisher]] +== The `publisher` role + +The `publisher` role can do the same as xref:authentication-authorization/built-in-roles.adoc#access-control-built-in-roles-editor[`editor`], as well as create new labels, property keys and relationship types. + + +[[access-control-built-in-roles-publisher-list]] +=== Listing `publisher` role privileges + +[source, cypher, role=noplay] +---- +SHOW ROLE publisher PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON DATABASE * TO `publisher`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `publisher`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `publisher`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `publisher`" +|"GRANT SHOW CONSTRAINT ON DATABASE * TO `publisher`" +|"GRANT SHOW INDEX ON DATABASE * TO `publisher`" +|"GRANT WRITE ON GRAPH * TO `publisher`" +a|Rows: 7 +|=== + + +[[access-control-built-in-roles-publisher-recreate]] +=== Recreating the `publisher` role + +//// +[source, cypher, role=test-setup] +---- +DROP ROLE publisher; +---- +//// + +To restore the role to its original capabilities two steps are needed. +First, execute `DROP ROLE publisher`. +Secondly, run these queries: + +[source, cypher, role=noplay] +---- +CREATE ROLE publisher +---- + +[source, cypher, role=noplay] +---- +GRANT ACCESS ON DATABASE * TO publisher +---- + +[source, cypher, role=noplay] +---- +GRANT MATCH {*} ON GRAPH * TO publisher +---- + +[source, cypher, role=noplay] +---- +GRANT WRITE ON GRAPH * TO publisher +---- + +[source, cypher, role=noplay] +---- +GRANT NAME MANAGEMENT ON DATABASE * TO publisher +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW CONSTRAINT ON DATABASE * TO publisher +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW INDEX ON DATABASE * TO publisher +---- + +The resulting `publisher` role now has the same privileges as the original built-in `publisher` role. + + +[[access-control-built-in-roles-architect]] +== The `architect` role + +The `architect` role can do the same as the xref:authentication-authorization/built-in-roles.adoc#access-control-built-in-roles-publisher[`publisher`], as well as create and manage indexes and constraints. + + +[[access-control-built-in-roles-architect-list]] +=== Listing `architect` role privileges + +[source, cypher, role=noplay] +---- +SHOW ROLE architect PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON DATABASE * TO `architect`" +|"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT INDEX MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `architect`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `architect`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT SHOW CONSTRAINT ON DATABASE * TO `architect`" +|"GRANT SHOW INDEX ON DATABASE * TO `architect`" +|"GRANT WRITE ON GRAPH * TO `architect`" +a|Rows: 9 +|=== + + +[[access-control-built-in-roles-architect-recreate]] +=== Recreating the `architect` role + +//// +[source, cypher, role=test-setup] +---- +DROP ROLE architect; +---- +//// + +To restore the role to its original capabilities two steps are needed. +First, execute `DROP ROLE architect`. +Secondly, run these queries: + +[source, cypher, role=noplay] +---- +CREATE ROLE architect +---- + +[source, cypher, role=noplay] +---- +GRANT ACCESS ON DATABASE * TO architect +---- + +[source, cypher, role=noplay] +---- +GRANT MATCH {*} ON GRAPH * TO architect +---- + +[source, cypher, role=noplay] +---- +GRANT WRITE ON GRAPH * TO architect +---- + +[source, cypher, role=noplay] +---- +GRANT NAME MANAGEMENT ON DATABASE * TO architect +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW CONSTRAINT ON DATABASE * TO architect +---- + +[source, cypher, role=noplay] +---- +GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO architect +---- + +[source, cypher, role=noplay] +---- +GRANT SHOW INDEX ON DATABASE * TO architect +---- + +[source, cypher, role=noplay] +---- +GRANT INDEX MANAGEMENT ON DATABASE * TO architect +---- + +The resulting `architect` role now has the same privileges as the original built-in `architect` role. + + +[[access-control-built-in-roles-admin]] +== The `admin` role + +The `admin` role can do the same as the xref:authentication-authorization/built-in-roles.adoc#access-control-built-in-roles-architect[`architect`], as well as manage databases, aliases, users, roles and privileges. + +The `admin` role can perform administrative tasks. +These include the rights to perform the following classes of tasks: + +* Manage xref:authentication-authorization/database-administration.adoc[database privileges] to control the rights to perform actions on specific databases: +** Manage access to a database and the right to start and stop a database. +** Manage link:{neo4j-docs-base-uri}/cypher-manual/5/indexes-for-search-performance/[indexes] and link:{neo4j-docs-base-uri}/cypher-manual/5/constraints/[constraints]. +** Allow the creation of labels, relationship types, or property names. +** Manage transactions. +* Manage xref:authentication-authorization/dbms-administration.adoc[DBMS privileges] to control the rights to perform actions on the entire system: +** Manage xref:database-administration/index.adoc[multiple databases]. +** Manage xref:authentication-authorization/manage-users.adoc[users] and xref:authentication-authorization/manage-roles.adoc[roles]. +** Change configuration parameters. +** Manage sub-graph privileges. +** Manage procedure security. +** Manage xref:authentication-authorization/load-privileges.adoc[load privileges] to control the rights to load data from external sources. + +These rights are conferred using privileges that can be managed through the xref:authentication-authorization/manage-privileges.adoc#access-control-graph-privileges[`GRANT`, `DENY` and `REVOKE` commands]. + + +[[access-control-built-in-roles-admin-list]] +=== Listing `admin` role privileges + +[source, cypher, role=noplay] +---- +SHOW ROLE admin PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON DATABASE * TO `admin`" +|"GRANT ALL DBMS PRIVILEGES ON DBMS TO `admin`" +|"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT INDEX MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT LOAD ON ALL DATA TO `admin`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `admin`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `admin`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT SHOW CONSTRAINT ON DATABASE * TO `admin`" +|"GRANT SHOW INDEX ON DATABASE * TO `admin`" +|"GRANT START ON DATABASE * TO `admin`" +|"GRANT STOP ON DATABASE * TO `admin`" +|"GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * TO `admin`" +|"GRANT WRITE ON GRAPH * TO `admin`" +a|Rows: 14 +|=== + +If the built-in `admin` role has been altered or dropped and needs to be restored to its original state, see xref:authentication-authorization/password-and-user-recovery.adoc[Password and user recovery]. + +[[access-control-built-in-roles-admin-recreate]] +=== Recreating the `admin` role + +To restore the role to its original capabilities two steps are needed. +First, execute `DROP ROLE admin`. +Secondly, run these queries: + +// cannot test as it would require deleting the role the test user is logged with +[source, cypher, role=noplay test-skip] +---- +CREATE ROLE admin +---- + +[source, cypher, role=noplay] +---- +GRANT ALL DBMS PRIVILEGES ON DBMS TO admin +---- + +[source, cypher, role=noplay] +---- +GRANT TRANSACTION MANAGEMENT ON DATABASE * TO admin +---- + +[source, cypher, role=noplay] +---- +GRANT START ON DATABASE * TO admin +---- + +[source, cypher, role=noplay] +---- +GRANT STOP ON DATABASE * TO admin +---- + +[source, cypher, role=noplay] +---- +GRANT MATCH {*} ON GRAPH * TO admin +---- + +[source, cypher, role=noplay] +---- +GRANT WRITE ON GRAPH * TO admin +---- + +[source, cypher, role=noplay] +---- +GRANT LOAD ON ALL DATA TO admin +---- + +[source, cypher, role=noplay] +---- +GRANT ALL ON DATABASE * TO admin +---- + +The resulting `admin` role now has the same effective privileges as the original built-in `admin` role. + +Additional information about restoring the `admin` role can be found in the xref:authentication-authorization/password-and-user-recovery.adoc[ Recover the admin role]. + diff --git a/modules/ROOT/pages/authentication-authorization/database-administration.adoc b/modules/ROOT/pages/authentication-authorization/database-administration.adoc new file mode 100644 index 000000000..62888c9ab --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/database-administration.adoc @@ -0,0 +1,985 @@ +:description: How to use Cypher to manage Neo4j database administrative privileges. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated + +//// +[source, cypher, role=test-setup] +---- +CREATE ROLE regularUsers; +CREATE ROLE databaseAdminUsers; +CREATE DATABASE `remote-db`; +CREATE USER jake SET PASSWORD 'abcd1234' CHANGE NOT REQUIRED; +---- +//// + + +[[access-control-database-administration]] += Database privileges + +Administrators can use the following Cypher commands to manage Neo4j database administrative rights. + +The components of the database privilege commands are: + +* _command_: +** `GRANT` – gives privileges to roles. +** `DENY` – denies privileges to roles. +** `REVOKE` – removes granted or denied privileges from roles. + +* _mutability_: +** `IMMUTABLE` - When used in conjunction with `GRANT` or `DENY`, specifies that a privilege cannot subsequently be removed unless auth is disabled. +Contrastingly, when `IMMUTABLE` is specified in conjunction with a `REVOKE` command, it will act as a filter and only remove matching _immutable_ privileges. +See also xref:authentication-authorization/immutable-roles-privileges.adoc[]. + +* _database-privilege_ +** `ACCESS` - allows access to a specific database or remote database alias. +** `START` - allows the specified database to be started. +** `STOP` - allows the specified database to be stopped. +** `CREATE INDEX` - allows indexes to be created on the specified database. +** `DROP INDEX` - allows indexes to be deleted on the specified database. +** `SHOW INDEX` - allows indexes to be listed on the specified database. +** `INDEX [MANAGEMENT]` - allows indexes to be created, deleted, and listed on the specified database. +** `CREATE CONSTRAINT` - allows constraints to be created on the specified database. +** `DROP CONSTRAINT` - allows constraints to be deleted on the specified database. +** `SHOW CONSTRAINT` - allows constraints to be listed on the specified database. +** `CONSTRAINT [MANAGEMENT]` - allows constraints to be created, deleted, and listed on the specified database. +** `CREATE NEW [NODE] LABEL` - allows new node labels to be created. +** `CREATE NEW [RELATIONSHIP] TYPE` - allows new relationship types to be created. +** `CREATE NEW [PROPERTY] NAME` - allows property names to be created, so that nodes and relationships can have properties assigned with these names. +** `NAME [MANAGEMENT]` - allows all of the name management capabilities: node labels, relationship types, and property names. +** `ALL [[DATABASE] PRIVILEGES]` - allows access, index, constraint, and name management for the specified database or remote database alias. +** `SHOW TRANSACTION` - allows listing transactions and queries for the specified users on the specified database. +** `TERMINATE TRANSACTION` - allows ending transactions and queries for the specified users on the specified database. +** `TRANSACTION [MANAGEMENT]` - allows listing and ending transactions and queries for the specified users on the specified database. + +* _name_ +** The database to associate the privilege with. ++ +[NOTE] +==== +If you delete a database and create a new one with the same name, the new one will NOT have the same privileges previously assigned to the deleted one. +==== +** The _name_ component can be `+*+`, which means all databases. +Databases created after this command execution will also be associated with these privileges. +** The `DATABASE[S] _name_` part of the command can be replaced by `HOME DATABASE`. +This refers to the home database configured for a user or, if that user does not have a home database configured, the default database. +If the user's home database changes for any reason after this command execution, the new one will be associated with these privileges. +This can be quite powerful as it allows permissions to be switched from one database to another simply by changing a user's home database. + +* _role[, ...]_ +** The role or roles to associate the privilege with, comma-separated. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.General grant +ON DATABASE+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT ... ON ... TO ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] database-privilege ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } TO role[, ...] +---- + +| Description +| Grants a privilege to one or multiple roles. + +|=== + + +.General deny +ON DATABASE+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +DENY ... ON ... TO ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +DENY [IMMUTABLE] database-privilege ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } TO role[, ...] +---- + +| Description +| Denies a privilege to one or multiple roles. + +|=== + + +.General revoke +ON DATABASE+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +REVOKE GRANT ... ON ... FROM ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +REVOKE [IMMUTABLE] GRANT database-privilege ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } FROM role[, ...] +---- + +| Description +| Revoke a granted privilege from one or multiple roles. + +|=== + + +.General revoke +ON DATABASE+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +REVOKE DENY ... ON ... FROM ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +REVOKE [IMMUTABLE] DENY database-privilege ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } FROM role[, ...] +---- + +| Description +| Revokes a denied privilege from one or multiple roles. + +|=== + + +.General revoke +ON DATABASE+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +REVOKE ... ON ... FROM ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +REVOKE [IMMUTABLE] database-privilege ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } FROM role[, ...] +---- + +| Description +| Revokes a granted or denied privilege from one or multiple roles. + +|=== + + +[NOTE] +==== +`DENY` does *not* erase a granted privilege. +Use `REVOKE` if you want to remove a privilege. +==== + +Common errors, such as misspellings or attempts to revoke privileges that have not been granted or denied, will lead to notifications. +Some of these notifications may be replaced with errors in a future major version of Neo4j. +See link:{neo4j-docs-base-uri}/status-codes/{page-version}/notifications/all-notifications[Status Codes for Errors & Notifications -> Server notifications] for details on notifications. + +The hierarchy between the different database privileges is shown in the image below. + +image::privileges_hierarchy_database.svg[title="Database privileges hierarchy"] + + + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT ACCESS+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] ACCESS + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +a| +Grants the specified roles the privilege to access: + +* The home database. +* Specific database(s) or remote database alias(es). +* All databases and remote database aliases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT { START \| STOP }+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] { START \| STOP } + ON { HOME DATABASE \| DATABASE[S] {* \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to start or stop the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT { CREATE \| DROP \| SHOW } INDEX+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] { CREATE \| DROP \| SHOW } INDEX[ES] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to create, delete, or show indexes on the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT INDEX+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] INDEX[ES] [MANAGEMENT] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to manage indexes on the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT { CREATE \| DROP \| SHOW } CONSTRAINT+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] { CREATE \| DROP \| SHOW } CONSTRAINT[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to create, delete, or show constraints on the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CONSTRAINT+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CONSTRAINT[S] [MANAGEMENT] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to manage constraints on the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CREATE NEW LABEL+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CREATE NEW [NODE] LABEL[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to create new node labels in the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CREATE NEW TYPE+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CREATE NEW [RELATIONSHIP] TYPE[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to create new relationship types in the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CREATE NEW NAME+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CREATE NEW [PROPERTY] NAME[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to create new property names in the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT NAME+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] NAME [MANAGEMENT] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to manage new labels, relationship types, and property names in the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT ALL+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] ALL [[DATABASE] PRIVILEGES] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles all privileges for the home, a specific, or all databases and remote database aliases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT { SHOW \| TERMINATE } TRANSACTION+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] { SHOW \| TERMINATE } TRANSACTION[S] [( { * \| user[, ...] } )] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to list and end the transactions and queries of all users or a particular user(s) in the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT TRANSACTION+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] TRANSACTION [MANAGEMENT] [( { * \| user[, ...] } )] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Grants the specified roles the privilege to manage the transactions and queries of all users or a particular user(s) in the home database, specific database(s), or all databases. + +|=== + + +image::privileges_grant_and_deny_syntax_database_privileges.svg[title="Syntax of GRANT and DENY Database Privileges"] + + +[[access-control-database-administration-access]] +== The database `ACCESS` privilege + +The `ACCESS` privilege enables users to connect to a database or a remote database alias. +With `ACCESS` you can run calculations, for example, `+RETURN 2 * 5 AS answer+` or call functions `RETURN timestamp() AS time`. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] ACCESS + ON { HOME DATABASE | DATABASE[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to access the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT ACCESS ON DATABASE neo4j TO regularUsers +---- + +The `ACCESS` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] ACCESS + ON { HOME DATABASE | DATABASE[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to access to the remote database alias `remote-db`, use: + +[source, cypher, role=noplay] +---- +DENY ACCESS ON DATABASE `remote-db` TO regularUsers +---- + +The privileges granted can be seen using the `SHOW PRIVILEGES` command: + +[source, cypher, role=noplay] +---- +SHOW ROLE regularUsers PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY ACCESS ON DATABASE `remote-db` TO `regularUsers`" +|"GRANT ACCESS ON DATABASE `neo4j` TO `regularUsers`" +a|Rows: 2 +|=== + + +[[access-control-database-administration-startstop]] +== The database `START`/`STOP` privileges + +The `START` privilege can be used to enable the ability to start a database: + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] START + ON { HOME DATABASE | DATABASE[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to start the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT START ON DATABASE neo4j TO regularUsers +---- + +The `START` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] START + ON { HOME DATABASE | DATABASE[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to start to the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +DENY START ON DATABASE system TO regularUsers +---- + +The `STOP` privilege can be used to enable the ability to stop a database: + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] STOP + ON { HOME DATABASE | DATABASE[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to stop the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT STOP ON DATABASE neo4j TO regularUsers +---- + +The `STOP` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] STOP + ON { HOME DATABASE | DATABASE[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to stop the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +DENY STOP ON DATABASE system TO regularUsers +---- + +The privileges granted can be seen using the `SHOW PRIVILEGES` command: + +[source, cypher, role=noplay] +---- +SHOW ROLE regularUsers PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY ACCESS ON DATABASE `remote-db` TO `regularUsers`" +|"DENY START ON DATABASE `system` TO `regularUsers`" +|"DENY STOP ON DATABASE `system` TO `regularUsers`" +|"GRANT ACCESS ON DATABASE `neo4j` TO `regularUsers`" +|"GRANT START ON DATABASE `neo4j` TO `regularUsers`" +|"GRANT STOP ON DATABASE `neo4j` TO `regularUsers`" +a|Rows: 6 +|=== + +[NOTE] +==== +Note that `START` and `STOP` privileges are not included in the xref:authentication-authorization/database-administration.adoc#access-control-database-administration-all[`ALL DATABASE PRIVILEGES`]. +==== + + +[[access-control-database-administration-index]] +== The `INDEX MANAGEMENT` privileges + +Indexes can be created, deleted, or listed with the `CREATE INDEX`, `DROP INDEX`, and `SHOW INDEXES` commands. +The privilege to do this can be granted with `GRANT CREATE INDEX`, `GRANT DROP INDEX`, and `GRANT SHOW INDEX` commands. +The privilege to do all three can be granted with `GRANT INDEX MANAGEMENT` command. + + + + +.Index management privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT { CREATE \| DROP \| SHOW } INDEX+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] { CREATE \| DROP \| SHOW } INDEX[ES] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to create, delete, or show indexes in the home database, specific database(s), or all databases. + +|=== + + + +.Index management privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT INDEX+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] INDEX[ES] [MANAGEMENT] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to manage indexes in the home database, specific database(s), or all databases. + +|=== + + +For example, to grant the role `regularUsers` the ability to create indexes on the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT CREATE INDEX ON DATABASE neo4j TO regularUsers +---- + + +[[access-control-database-administration-constraints]] +== The `CONSTRAINT MANAGEMENT` privileges + +Constraints can be created, deleted, or listed with the `CREATE CONSTRAINT`, `DROP CONSTRAINT` and `SHOW CONSTRAINTS` commands. +The privilege to do this can be granted with `GRANT CREATE CONSTRAINT`, `GRANT DROP CONSTRAINT`, `GRANT SHOW CONSTRAINT` commands. +The privilege to do all three can be granted with `GRANT CONSTRAINT MANAGEMENT` command. + + +.Constraint management privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT { CREATE \| DROP \| SHOW } CONSTRAINT+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] { CREATE \| DROP \| SHOW } CONSTRAINT[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to create, delete, or show constraints on the home database, specific database(s), or all databases. + +|=== + + +.Constraint management privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CONSTRAINT+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CONSTRAINT[S] [MANAGEMENT] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enable the specified roles to manage constraints on the home database, specific database(s), or all databases. + +|=== + + +For example, to grant the role `regularUsers` the ability to create constraints on the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT CREATE CONSTRAINT ON DATABASE neo4j TO regularUsers +---- + + +[[access-control-database-administration-tokens]] +== The `NAME MANAGEMENT` privileges + +The right to create new labels, relationship types, and property names is different from the right to create nodes, relationships, and properties. +The latter is managed using database `WRITE` privileges, while the former is managed using specific `+GRANT/DENY CREATE NEW ...+` commands for each type. + + +.Node label management privileges syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CREATE NEW LABEL+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CREATE NEW [NODE] LABEL[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to create new node labels in the home database, specific database(s), or all databases. + +|=== + + +.Relationship type management privileges syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CREATE NEW TYPE+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CREATE NEW [RELATIONSHIP] TYPE[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to create new relationship types in the home database, specific database(s), or all databases. + +|=== + + +.Property name management privileges syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT CREATE NEW NAME+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] CREATE NEW [PROPERTY] NAME[S] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to create new property names in the home database, specific database(s), or all databases. + +|=== + + +.Node label, relationship type, and property name privileges management syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT NAME+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] NAME [MANAGEMENT] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to create new labels, relationship types, and property names in the home database, specific database(s), or all databases. + +|=== + +[NOTE] +==== +The `SHOW PRIVILEGES` commands return the `NAME MANAGEMENT` privilege as the action `token`, when not using `AS COMMANDS`. +==== + +For example, to grant the role `regularUsers` the ability to create new properties on nodes or relationships on the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT CREATE NEW PROPERTY NAME ON DATABASE neo4j TO regularUsers +---- + + +[[access-control-database-administration-all]] +== Granting `ALL DATABASE PRIVILEGES` + +The right to access a database, create and drop indexes and constraints and create new labels, relationship types or property names can be achieved with a single command: + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] ALL [[DATABASE] PRIVILEGES] + ON { HOME DATABASE | DATABASE[S] { * | name[, ...] } } + TO role[, ...] +---- + +[NOTE] +==== +Note that the privileges for starting and stopping all databases, and transaction management, are not included in the `ALL DATABASE PRIVILEGES` grant. +These privileges are associated with administrators while other database privileges are of use to domain and application developers. +==== + +For example, granting the abilities above on the database `neo4j` to the role `databaseAdminUsers` is done using the following query. + +[source, cypher, role=noplay] +---- +GRANT ALL DATABASE PRIVILEGES ON DATABASE neo4j TO databaseAdminUsers +---- + +The privileges granted can be seen using the `SHOW PRIVILEGES` command: + +[source, cypher, role=noplay] +---- +SHOW ROLE databaseAdminUsers PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ALL DATABASE PRIVILEGES ON DATABASE `neo4j` TO `databaseAdminUsers`" +a|Rows: 1 +|=== + + +[[access-control-database-administration-transaction]] +== Granting `TRANSACTION MANAGEMENT` privileges + +The right to run the commands `SHOW TRANSACTIONS`, `TERMINATE TRANSACTIONS`, and the deprecated procedures `dbms.listTransactions`, `dbms.listQueries`, `dbms.killQuery`, `dbms.killQueries`, `dbms.killTransaction` and `dbms.killTransactions` is now managed through the `SHOW TRANSACTION` and `TERMINATE TRANSACTION` privileges. + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT SHOW TRANSACTION+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] SHOW TRANSACTION[S] [( { * \| user[, ...] } )] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to list transactions and queries for user(s) or all users in the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT TERMINATE TRANSACTION+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] TERMINATE TRANSACTION[S] [( { * \| user[, ...] } )] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to end running transactions and queries for user(s) or all users in the home database, specific database(s), or all databases. + +|=== + + +.Database privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT TRANSACTION+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] TRANSACTION [MANAGEMENT] [( { * \| user[, ...] } )] + ON { HOME DATABASE \| DATABASE[S] { * \| name[, ...] } } + TO role[, ...] +---- + +| Description +| Enables the specified roles to manage transactions and queries for user(s) or all users in the home database, specific database(s), or all databases. + +|=== + + +[NOTE] +==== +Note that the `TRANSACTION MANAGEMENT` privileges are not included in the xref:authentication-authorization/database-administration.adoc#access-control-database-administration-all[`ALL DATABASE PRIVILEGES`]. +==== + +For example, to grant the role `regularUsers` the ability to list transactions for user `jake` on the database `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT SHOW TRANSACTION (jake) ON DATABASE neo4j TO regularUsers +---- diff --git a/modules/ROOT/pages/authentication-authorization/dbms-administration.adoc b/modules/ROOT/pages/authentication-authorization/dbms-administration.adoc new file mode 100644 index 000000000..347799233 --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/dbms-administration.adoc @@ -0,0 +1,2139 @@ +:description: How to use Cypher to manage Neo4j DBMS administrative privileges. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated +//// +[source, cypher, role=test-setup] +---- +CREATE USER jake SET PASSWORD 'abcd1234' CHANGE NOT REQUIRED; +CREATE ROLE roleAdder IF NOT EXISTS; +CREATE ROLE roleNameModifier IF NOT EXISTS; +CREATE ROLE roleDropper IF NOT EXISTS; +CREATE ROLE roleAssigner IF NOT EXISTS; +CREATE ROLE roleRemover IF NOT EXISTS; +CREATE ROLE roleShower IF NOT EXISTS; +CREATE ROLE roleManager IF NOT EXISTS; +CREATE ROLE userAdder IF NOT EXISTS; +CREATE ROLE userNameModifier IF NOT EXISTS; +CREATE ROLE userModifier IF NOT EXISTS; +CREATE ROLE passwordModifier IF NOT EXISTS; +CREATE ROLE statusModifier IF NOT EXISTS; +CREATE ROLE userDropper IF NOT EXISTS; +CREATE ROLE userShower IF NOT EXISTS; +CREATE ROLE userManager IF NOT EXISTS; +CREATE ROLE userImpersonator IF NOT EXISTS; +CREATE ROLE databaseAdder IF NOT EXISTS; +CREATE ROLE compositeDatabaseAdder IF NOT EXISTS; +CREATE ROLE databaseDropper IF NOT EXISTS; +CREATE ROLE compositeDatabaseDropper IF NOT EXISTS; +CREATE ROLE databaseModifier IF NOT EXISTS; +CREATE ROLE accessModifier IF NOT EXISTS; +CREATE ROLE compositeDatabaseManager IF NOT EXISTS; +CREATE ROLE databaseManager IF NOT EXISTS; +CREATE ROLE aliasAdder IF NOT EXISTS; +CREATE ROLE aliasDropper IF NOT EXISTS; +CREATE ROLE aliasModifier IF NOT EXISTS; +CREATE ROLE aliasLister IF NOT EXISTS; +CREATE ROLE aliasManager IF NOT EXISTS; +CREATE ROLE privilegeShower IF NOT EXISTS; +CREATE ROLE privilegeAssigner IF NOT EXISTS; +CREATE ROLE privilegeRemover IF NOT EXISTS; +CREATE ROLE privilegeManager IF NOT EXISTS; +CREATE ROLE procedureExecutor IF NOT EXISTS; +CREATE ROLE deniedProcedureExecutor IF NOT EXISTS; +CREATE ROLE boostedProcedureExecutor IF NOT EXISTS; +CREATE ROLE deniedBoostedProcedureExecutor1 IF NOT EXISTS; +CREATE ROLE deniedBoostedProcedureExecutor2 IF NOT EXISTS; +CREATE ROLE deniedBoostedProcedureExecutor3 IF NOT EXISTS; +CREATE ROLE deniedBoostedProcedureExecutor4 IF NOT EXISTS; +CREATE ROLE adminProcedureExecutor IF NOT EXISTS; +CREATE ROLE functionExecutor IF NOT EXISTS; +CREATE ROLE deniedFunctionExecutor IF NOT EXISTS; +CREATE ROLE boostedFunctionExecutor IF NOT EXISTS; +CREATE ROLE globbing1 IF NOT EXISTS; +CREATE ROLE globbing2 IF NOT EXISTS; +CREATE ROLE globbing3 IF NOT EXISTS; +CREATE ROLE globbing4 IF NOT EXISTS; +CREATE ROLE globbing5 IF NOT EXISTS; +CREATE ROLE globbing6 IF NOT EXISTS; +CREATE ROLE dbmsManager IF NOT EXISTS; +CREATE ROLE configurationViewer IF NOT EXISTS; +CREATE ROLE deniedConfigurationViewer IF NOT EXISTS; +---- +//// + +[[access-control-dbms-administration]] += DBMS privileges + +All DBMS privileges are relevant system-wide. +Like user management, they do not belong to one specific database or graph. +For more details on the differences between graphs, databases, and the DBMS, refer to link:{neo4j-docs-base-uri}/cypher-manual/5/introduction/cypher_neo4j/[Cypher Manual -> Cypher and Neo4j]. + +image::privileges_grant_and_deny_syntax_dbms_privileges.svg[title="Syntax of GRANT and DENY DBMS Privileges"] + +image::privileges_hierarchy_dbms.svg[title="DBMS privileges hierarchy"] + +The xref:authentication-authorization/built-in-roles.adoc#access-control-built-in-roles-admin[`admin` role] has a number of built-in privileges. +These include: + +* Create, delete, and modify databases and aliases. +* Change configuration parameters. +* Manage transactions. +* Manage users and roles. +* Manage sub-graph privileges. +* Manage procedure security. +* Load data. + +To enable a user to perform these tasks, you can grant them the `admin` role, but it is also possible to make a custom role with a subset of these privileges. +All privileges are also assignable using Cypher commands. +For more details, see the following sections: + +* <> +* <> +* <> +* <> +* <> +* <> +* xref:authentication-authorization/database-administration.adoc#access-control-database-administration-transaction[Transaction management] +* <> +* xref:authentication-authorization/load-privileges.adoc[Load privileges] + +[[access-control-dbms-administration-custom]] +== Using a custom role to manage DBMS privileges + +In order to have an administrator role with a subset of privileges that includes all DBMS privileges, but not all database privileges, you can copy the `admin` role and revoke or deny the unwanted privileges. +A second option is to build a custom administrator from scratch by granting the wanted privileges instead. + +As an example, an administrator role can be created to only manage users and roles by using the second option: + +. First, create the new role: ++ +[source, cypher, role=noplay] +---- +CREATE ROLE usermanager +---- +. Then grant the privilege to manage users: ++ +[source, cypher, role=noplay] +---- +GRANT USER MANAGEMENT ON DBMS TO usermanager +---- +. And to manage roles: ++ +[source, cypher, role=noplay] +---- +GRANT ROLE MANAGEMENT ON DBMS TO usermanager +---- + +The resulting role has privileges that only allow user and role management. +To list all privileges for the role `usermanager` as commands, run this query: + +[source, cypher, role=noplay] +---- +SHOW ROLE usermanager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ROLE MANAGEMENT ON DBMS TO `usermanager`" +|"GRANT USER MANAGEMENT ON DBMS TO `usermanager`" +a|Rows: 2 +|=== + +Note that this role does not allow all DBMS capabilities. +For example, the role is missing privileges for management, creation and drop of databases as well as execution of `admin` procedures. +To create a more powerful administrator, you can grant a different set of privileges. + +In the following example, a new administrator role is created to perform almost all DBMS capabilities, excluding database management. +However, the role still has some limited database capabilities, such as managing transactions: + +. Again, start by creating a new role: ++ +[source, cypher, role=noplay] +---- +CREATE ROLE customAdministrator +---- +. Then grant the privilege for all DBMS capabilities: ++ +[source, cypher, role=noplay] +---- +GRANT ALL DBMS PRIVILEGES ON DBMS TO customAdministrator +---- +. And explicitly deny the privilege to manage databases: ++ +[source, cypher, role=noplay] +---- +DENY DATABASE MANAGEMENT ON DBMS TO customAdministrator +---- +. Next, grant the transaction management privilege: ++ +[source, cypher, role=noplay] +---- +GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * TO customAdministrator +---- + +The resulting role has privileges that include all DBMS privileges except creating, dropping, and modifying databases, as well as managing transactions. +Use the following query to list all privileges for the role `customAdministrator` as commands: + +[source, cypher, role=noplay] +---- +SHOW ROLE customAdministrator PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY DATABASE MANAGEMENT ON DBMS TO `customAdministrator`" +|"GRANT ALL DBMS PRIVILEGES ON DBMS TO `customAdministrator`" +|"GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * TO `customAdministrator`" +a|Rows: 3 +|=== + + +[[access-control-dbms-administration-role-management]] +== The DBMS `ROLE MANAGEMENT` privileges + +The DBMS privileges for role management are assignable using Cypher administrative commands. +They can be granted, denied, and revoked like other privileges. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.Role management privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] CREATE ROLE + ON DBMS + TO role[, ...] +| Enables the specified roles to create new roles. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] RENAME ROLE + ON DBMS + TO role[, ...] +| Enables the specified roles to change the name of roles. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] DROP ROLE + ON DBMS + TO role[, ...] +| Enables the specified roles to delete roles. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] ASSIGN ROLE + ON DBMS + TO role[, ...] +| Enables the specified roles to assign roles to users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] REMOVE ROLE + ON DBMS + TO role[, ...] +| Enables the specified roles to remove roles from users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SHOW ROLE + ON DBMS + TO role[, ...] +| Enables the specified roles to list roles. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] ROLE MANAGEMENT + ON DBMS + TO role[, ...] +| Enables the specified roles to create, delete, assign, remove, and list roles. + +|=== + +The ability to add roles can be granted via the `CREATE ROLE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT CREATE ROLE ON DBMS TO roleAdder +---- + +The resulting role has privileges that only allow adding roles. +List all privileges for the role `roleAdder` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE roleAdder PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT CREATE ROLE ON DBMS TO `roleAdder`" +a|Rows: 1 +|=== + +The ability to rename roles can be granted via the `RENAME ROLE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT RENAME ROLE ON DBMS TO roleNameModifier +---- + +The resulting role has privileges that only allow renaming roles. +List all privileges for the role `roleNameModifier` using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE roleNameModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT RENAME ROLE ON DBMS TO `roleNameModifier`" +a|Rows: 1 +|=== + +The ability to delete roles can be granted via the `DROP ROLE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT DROP ROLE ON DBMS TO roleDropper +---- + +The resulting role has privileges that only allow deleting roles. +List all privileges for the role `roleDropper` by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE roleDropper PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT DROP ROLE ON DBMS TO `roleDropper`" +a|Rows: 1 +|=== + +The ability to assign roles to users can be granted via the `ASSIGN ROLE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT ASSIGN ROLE ON DBMS TO roleAssigner +---- + +The resulting role has privileges that only allow assigning/granting roles. +List all privileges for the role `roleAssigner` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE roleAssigner PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ASSIGN ROLE ON DBMS TO `roleAssigner`" +a|Rows: 1 +|=== + +The ability to remove roles from users can be granted via the `REMOVE ROLE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT REMOVE ROLE ON DBMS TO roleRemover +---- + +The resulting role has privileges that only allow removing/revoking roles. +List all privileges for the role `roleRemover` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE roleRemover PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT REMOVE ROLE ON DBMS TO `roleRemover`" +a|Rows: 1 +|=== + +The ability to show roles can be granted via the `SHOW ROLE` privilege. +A role with this privilege is allowed to execute the `SHOW ROLES` and `SHOW POPULATED ROLES` administration commands. +For the `SHOW ROLES WITH USERS` and `SHOW POPULATED ROLES WITH USERS` administration commands, both this privilege and the `SHOW USER` privilege are required. +The following query shows an example of how to grant the `SHOW ROLE` privilege: + +In order to use `SHOW ROLES WITH USERS` and `SHOW POPULATED ROLES WITH USERS` administration commands, both the `SHOW ROLE` and the `SHOW USER` privileges are required. +See an example of how to grant the `SHOW ROLE` privilege: + +[source, cypher, role=noplay] +---- +GRANT SHOW ROLE ON DBMS TO roleShower +---- + +The resulting role has privileges that only allow showing roles. +List all privileges for the role `roleShower` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE roleShower PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SHOW ROLE ON DBMS TO `roleShower`" +a|Rows: 1 +|=== + +The privileges to create, rename, delete, assign, remove, and list roles can be granted via the `ROLE MANAGEMENT` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT ROLE MANAGEMENT ON DBMS TO roleManager +---- + +The resulting role has all privileges to manage roles. +List all privileges for the role `roleManager` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE roleManager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ROLE MANAGEMENT ON DBMS TO `roleManager`" +a|Rows: 1 +|=== + + +[[access-control-dbms-administration-user-management]] +== The DBMS `USER MANAGEMENT` privileges + +The DBMS privileges for user management can be assigned using Cypher administrative commands. +They can be granted, denied, and revoked like other privileges. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.User management privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] CREATE USER + ON DBMS + TO role[, ...] +| Enables the specified roles to create new users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] RENAME USER + ON DBMS + TO role[, ...] +| Enables the specified roles to change the name of users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] ALTER USER + ON DBMS + TO role[, ...] +| Enables the specified roles to modify users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SET PASSWORD[S] + ON DBMS + TO role[, ...] +| Enables the specified roles to modify users' passwords and whether those passwords must be changed upon first login. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SET AUTH + ON DBMS + TO role[, ...] +| label:new[Introduced in 5.24] Enables the specified roles to `SET` or `REMOVE` users' xref:authentication-authorization/auth-providers.adoc[auth providers]. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SET USER HOME DATABASE + ON DBMS + TO role[, ...] +| Enables the specified roles to modify users' home database. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SET USER STATUS + ON DBMS + TO role[, ...] +| Enables the specified roles to modify the account status of users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] DROP USER + ON DBMS + TO role[, ...] +| Enables the specified roles to delete users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SHOW USER + ON DBMS + TO role[, ...] +| Enables the specified roles to list users. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] USER MANAGEMENT + ON DBMS + TO role[, ...] +| Enables the specified roles to create, delete, modify, and list users. + +|=== + +The ability to add users can be granted via the `CREATE USER` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT CREATE USER ON DBMS TO userAdder +---- + +The resulting role has privileges that only allow adding users. +List all privileges for the role `userAdder` as commands by using this query: + +[source, cypher, role=noplay] +---- +SHOW ROLE userAdder PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT CREATE USER ON DBMS TO `userAdder`" +a|Rows: 1 +|=== + +The ability to rename users can be granted via the `RENAME USER` privilege. +The following query shows an example of this: + +[source, cypher, role=noplay] +---- +GRANT RENAME USER ON DBMS TO userNameModifier +---- + +The resulting role has privileges that only allow renaming users: + +[source, cypher, role=noplay] +---- +SHOW ROLE userNameModifier PRIVILEGES AS COMMANDS +---- + +Lists all privileges for role `userNameModifier`: + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT RENAME USER ON DBMS TO `userNameModifier`" +a|Rows: 1 +|=== + +The ability to modify users can be granted via the `ALTER USER` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT ALTER USER ON DBMS TO userModifier +---- + +The resulting role has privileges that only allow modifying users. +List all privileges for the role `userModifier` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE userModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ALTER USER ON DBMS TO `userModifier`" +a|Rows: 1 +|=== + +A user that is granted the `ALTER USER` privilege is allowed to run the `ALTER USER` administration command with one or several of the `SET PASSWORD`, `SET PASSWORD CHANGE [NOT] REQUIRED`, `SET AUTH`, `REMOVE AUTH` and `SET STATUS` parts: + +[source, cypher, role=noplay] +---- +ALTER USER jake SET PASSWORD 'verysecret' SET STATUS SUSPENDED +---- + +The ability to modify users' passwords and whether those passwords must be changed upon first login can be granted via the `SET PASSWORDS` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT SET PASSWORDS ON DBMS TO passwordModifier +---- + +The resulting role has privileges that only allow modifying users' passwords and whether those passwords must be changed upon first login. +List all privileges for the role `passwordModifier` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE passwordModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SET PASSWORD ON DBMS TO `passwordModifier`" +a|Rows: 1 +|=== + +A user that is granted the `SET PASSWORDS` privilege is allowed to run the `ALTER USER` administration command with one or both of the `SET PASSWORD` and `SET PASSWORD CHANGE [NOT] REQUIRED` parts: + +[source, cypher, role=noplay] +---- +ALTER USER jake SET PASSWORD 'abcd5678' CHANGE NOT REQUIRED +---- + +label:new[Introduced in 5.24] A user that is granted the `SET AUTH` privilege is allowed to run the `ALTER USER` administration command with one or both of the `SET AUTH` and `REMOVE AUTH` parts: + +[source, cypher, role=noplay] +---- +ALTER USER jake REMOVE AUTH 'native SET AUTH 'oidc-okta' { SET id 'jakesUniqueOktaUserId' } +---- + + +The ability to modify the account status of users can be granted via the `SET USER STATUS` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT SET USER STATUS ON DBMS TO statusModifier +---- + +The resulting role has privileges that only allow modifying the account status of users. +List all privileges for the role `statusModifier` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE statusModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SET USER STATUS ON DBMS TO `statusModifier`" +a|Rows: 1 +|=== + +A user that is granted the `SET USER STATUS` privilege is allowed to run the `ALTER USER` administration command with only the `SET STATUS` part: + +[source, cypher, role=noplay] +---- +ALTER USER jake SET STATUS ACTIVE +---- + +In order to be able to modify the home database of users, grant the `SET USER HOME DATABASE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT SET USER HOME DATABASE ON DBMS TO statusModifier +---- + +The resulting role has privileges that only allow modifying the home database of users. +List all privileges for the role `statusModifier` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE statusModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SET USER HOME DATABASE ON DBMS TO `statusModifier`" +|"GRANT SET USER STATUS ON DBMS TO `statusModifier`" +a|Rows: 2 +|=== + +A user that is granted the `SET USER HOME DATABASE` privilege is allowed to run the `ALTER USER` administration command with only the `SET HOME DATABASE` or `REMOVE HOME DATABASE` part: + +[source, cypher, role=noplay] +---- +ALTER USER jake SET HOME DATABASE otherDb +---- + +[source, cypher, role=noplay] +---- +ALTER USER jake REMOVE HOME DATABASE +---- + +[NOTE] +==== +Note that the combination of the `SET PASSWORDS`, `SET AUTH`, `SET USER STATUS`, and the `SET USER HOME DATABASE` privilege actions is equivalent to the `ALTER USER` privilege action. +==== + +The ability to delete users can be granted via the `DROP USER` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT DROP USER ON DBMS TO userDropper +---- + +The resulting role has privileges that only allow deleting users. +List all privileges for the role `userDropper` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE userDropper PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT DROP USER ON DBMS TO `userDropper`" +a|Rows: 1 +|=== + +The ability to show users can be granted via the `SHOW USER` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT SHOW USER ON DBMS TO userShower +---- + +The resulting role has privileges that only allow showing users. +List all privileges for the role `userShower` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE userShower PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SHOW USER ON DBMS TO `userShower`" +a|Rows: 1 +|=== + +The privileges to create, rename, modify, delete, and list users can be granted via the `USER MANAGEMENT` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT USER MANAGEMENT ON DBMS TO userManager +---- + +The resulting role has all privileges to manage users. +List all privileges for the role `userManager` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE userManager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SHOW USER ON DBMS TO `userManager`" +a|Rows: 1 +|=== + +[[access-control-dbms-administration-impersonation]] +== The DBMS `IMPERSONATE` privileges + +The DBMS privileges for impersonation can be assigned through Cypher administrative commands. +They can be granted, denied, and revoked like other privileges. + +Impersonation is the ability of a user to assume another user's roles (and therefore privileges), with the restriction of not being able to execute updating `admin` commands as the impersonated user (i.e. they would still be able to use `SHOW` commands). + +The ability to impersonate users can be granted via the `IMPERSONATE` privilege. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.Impersonation privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] IMPERSONATE [(*)] + ON DBMS + TO role[, ...] +| Enables the specified roles to impersonate any user. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] IMPERSONATE (user[, ...]) + ON DBMS + TO role[, ...] +| Enables the specified roles to impersonate the specified users. + +|=== + +The following query shows an example of this. +Note that `userImpersonator` must be an existing role in order to make this query work: + +.Query +[source, cypher, role=noplay] +---- +GRANT IMPERSONATE (*) ON DBMS TO userImpersonator +---- + +The resulting role has privileges that allow impersonating all users: + +.Query +[source, cypher, role=noplay] +---- +SHOW ROLE userImpersonator PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +| command +| "GRANT IMPERSONATE (*) ON DBMS TO `userImpersonator`" +a|Rows: 1 +|=== + +It is also possible to deny and revoke that privilege. +See an example which shows of how the `userImpersonator` user would be able to impersonate all users, except `alice`: + +.Query +[source, cypher, role=noplay] +---- +DENY IMPERSONATE (alice) ON DBMS TO userImpersonator +---- + +To grant (or revoke) the permissions to impersonate a specific user or a subset of users, you can first list them with this query: + +.Query +[source, cypher, role=noplay] +---- +GRANT IMPERSONATE (alice, bob) ON DBMS TO userImpersonator +---- + + +[[access-control-dbms-administration-database-management]] +== The DBMS `DATABASE MANAGEMENT` privileges + +The DBMS privileges for database management can be assigned by using Cypher administrative commands. +They can be granted, denied and revoked like other privileges. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.Database management privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] CREATE DATABASE + ON DBMS + TO role[, ...] +| Enables the specified roles to create new standard databases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] DROP DATABASE + ON DBMS + TO role[, ...] +| Enables the specified roles to delete standard databases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] ALTER DATABASE + ON DBMS + TO role[, ...] +| Enables the specified roles to modify standard databases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SET DATABASE ACCESS + ON DBMS + TO role[, ...] +| Enables the specified roles to modify access to standard databases. + +| [source, syntax, role=noheader] +GRANT CREATE COMPOSITE DATABASE + ON DBMS + TO role[, ...] +| Enables the specified roles to create new composite databases. + +| [source, syntax, role=noheader] +GRANT DROP COMPOSITE DATABASE + ON DBMS + TO role[, ...] +| Enables the specified roles to delete composite databases. + +| [source, syntax, role=noheader] +GRANT COMPOSITE DATABASE MANAGEMENT + ON DBMS + TO role[, ...] +| Enables the specified roles to create and delete composite databases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] DATABASE MANAGEMENT + ON DBMS + TO role[, ...] +| Enables the specified roles to create, delete, and modify databases. + +|=== + + +The ability to create standard databases can be granted via the `CREATE DATABASE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT CREATE DATABASE ON DBMS TO databaseAdder +---- + +The resulting role has privileges that only allow creating standard databases. +List all privileges for the role `databaseAdder` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE databaseAdder PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT CREATE DATABASE ON DBMS TO `databaseAdder`" +a|Rows: 1 +|=== + +The ability to create composite databases can be granted via the `CREATE COMPOSITE DATABASE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT CREATE COMPOSITE DATABASE ON DBMS TO compositeDatabaseAdder +---- + +The resulting role has privileges that only allow creating composite databases. +List all privileges for the role `compositeDatabaseAdder` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE compositeDatabaseAdder PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT CREATE COMPOSITE DATABASE ON DBMS TO `compositeDatabaseAdder`" +a|Rows: 1 +|=== + +The ability to delete standard databases can be granted via the `DROP DATABASE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT DROP DATABASE ON DBMS TO databaseDropper +---- + +The resulting role has privileges that only allow deleting standard databases. +List all privileges for the role `databaseDropper` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE databaseDropper PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT DROP DATABASE ON DBMS TO `databaseDropper`" +a|Rows: 1 +|=== + +The ability to delete composite databases can be granted via the `DROP COMPOSITE DATABASE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT DROP COMPOSITE DATABASE ON DBMS TO compositeDatabaseDropper +---- + +The resulting role has privileges that only allow deleting composite databases. +List all privileges for the role `compositeDatabaseDropper` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE compositeDatabaseDropper PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT DROP COMPOSITE DATABASE ON DBMS TO `compositeDatabaseDropper`" +a|Rows: 1 +|=== + +The ability to modify standard databases can be granted via the `ALTER DATABASE` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT ALTER DATABASE ON DBMS TO databaseModifier +---- + +The resulting role has privileges that only allow modifying standard databases. +List all privileges for the role `databaseModifier` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE databaseModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ALTER DATABASE ON DBMS TO `databaseModifier`" +a|Rows: 1 +|=== + +The ability to modify access to standard databases can be granted via the `SET DATABASE ACCESS` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT SET DATABASE ACCESS ON DBMS TO accessModifier +---- + +The resulting role has privileges that only allow modifying access to standard databases. +List all privileges for the role `accessModifier` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE accessModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SET DATABASE ACCESS ON DBMS TO `accessModifier`" +a|Rows: 1 +|=== + +The ability to create and delete composite databases can be granted via the `COMPOSITE DATABASE MANAGEMENT` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT COMPOSITE DATABASE MANAGEMENT ON DBMS TO compositeDatabaseManager +---- + +The resulting role has all privileges to manage composite databases. +List all privileges for the role `compositeDatabaseManager` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE compositeDatabaseManager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT COMPOSITE DATABASE MANAGEMENT ON DBMS TO `compositeDatabaseManager`" +a|Rows: 1 +|=== + +The ability to create, delete, and modify databases can be granted via the `DATABASE MANAGEMENT` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT DATABASE MANAGEMENT ON DBMS TO databaseManager +---- + +The resulting role has all privileges to manage standard and composite databases. +List all privileges for the role `databaseManager` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE databaseManager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT DATABASE MANAGEMENT ON DBMS TO `databaseManager`" +a|Rows: 1 +|=== + +[[access-control-dbms-administration-alias-management]] +== The DBMS `ALIAS MANAGEMENT` privileges + +The DBMS privileges for alias management can be assigned by using Cypher administrative commands and can be applied to both local and remote aliases. +They can be granted, denied and revoked like other privileges. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.Alias management privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] CREATE ALIAS +ON DBMS +TO role[, ...] +| Enables the specified roles to create new aliases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] DROP ALIAS +ON DBMS +TO role[, ...] +| Enables the specified roles to delete aliases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] ALTER ALIAS +ON DBMS +TO role[, ...] +| Enables the specified roles to modify aliases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SHOW ALIAS +ON DBMS +TO role[, ...] +| Enables the specified roles to list aliases. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] ALIAS MANAGEMENT +ON DBMS +TO role[, ...] +| Enables the specified roles to list, create, delete, and modify aliases. + +|=== + +The ability to create aliases can be granted via the `CREATE ALIAS` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT CREATE ALIAS ON DBMS TO aliasAdder +---- + +The resulting role has privileges that only allow creating aliases. +List all privileges for the role `aliasAdder` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE aliasAdder PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT CREATE ALIAS ON DBMS TO `aliasAdder`" +a|Rows: 1 +|=== + +The ability to delete aliases can be granted via the `DROP ALIAS` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT DROP ALIAS ON DBMS TO aliasDropper +---- + +The resulting role has privileges that only allow deleting aliases. +See all privileges for the role `aliasDropper` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE aliasDropper PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT DROP ALIAS ON DBMS TO `aliasDropper`" +a|Rows: 1 +|=== + +The ability to modify aliases can be granted via the `ALTER ALIAS` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT ALTER ALIAS ON DBMS TO aliasModifier +---- + +The resulting role has privileges that only allow modifying aliases. +List all privileges for the role `aliasModifier` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE aliasModifier PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ALTER ALIAS ON DBMS TO `aliasModifier`" +a|Rows: 1 +|=== + +The ability to list aliases can be granted via the `SHOW ALIAS` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT SHOW ALIAS ON DBMS TO aliasLister +---- + +The resulting role has privileges that only allow modifying aliases. +List all privileges for the role `aliasLister` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE aliasLister PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SHOW ALIAS ON DBMS TO `aliasLister`" +a|Rows: 1 +|=== + +The privileges to list, create, delete, and modify aliases can be granted via the `ALIAS MANAGEMENT` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT ALIAS MANAGEMENT ON DBMS TO aliasManager +---- + +The resulting role has all privileges to manage aliases. +List all privileges for the role `aliasManager` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE aliasManager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ALIAS MANAGEMENT ON DBMS TO `aliasManager`" +a|Rows: 1 +|=== + +[[access-control-dbms-administration-server-management]] +== The DBMS `SERVER MANAGEMENT` privileges + +The DBMS privileges for server management can be assigned using Cypher administrative commands. +They can be granted, denied, and revoked like other privileges. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc#administration-syntax-reading[Reading the administration commands syntax]. +==== + +.Server management privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SERVER MANAGEMENT + ON DBMS + TO role[, ...] +| Enables the specified roles to show, enable, rename, alter, reallocate, deallocate, and drop servers. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SHOW SERVERS + ON DBMS + TO role[, ...] +| Enables the specified roles to show servers. +|=== + + +[[access-control-dbms-administration-privilege-management]] +== The DBMS `PRIVILEGE MANAGEMENT` privileges + +The DBMS privileges for privilege management can be assigned by using Cypher administrative commands. +They can be granted, denied and revoked like other privileges. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.Privilege management privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SHOW PRIVILEGE + ON DBMS + TO role[, ...] +| Enables the specified roles to list privileges. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] ASSIGN PRIVILEGE + ON DBMS + TO role[, ...] +| Enables the specified roles to assign privileges using the `GRANT` and `DENY` commands. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] REMOVE PRIVILEGE + ON DBMS + TO role[, ...] +| Enables the specified roles to remove privileges using the `REVOKE` command. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] PRIVILEGE MANAGEMENT + ON DBMS + TO role[, ...] +| Enables the specified roles to list, assign, and remove privileges. +|=== + +The ability to list privileges can be granted via the `SHOW PRIVILEGE` privilege. + +A user with this privilege is allowed to execute the `SHOW PRIVILEGES` and `SHOW ROLE roleName PRIVILEGES` administration commands. +To execute the `SHOW USER username PRIVILEGES` administration command, both this privilege and the `SHOW USER` privilege are required. +The following query shows an example of how to grant the `SHOW PRIVILEGE` privilege: + +[source, cypher, role=noplay] +---- +GRANT SHOW PRIVILEGE ON DBMS TO privilegeShower +---- + +The resulting role has privileges that only allow showing privileges. +List all privileges for the role `privilegeShower` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE privilegeShower PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SHOW PRIVILEGE ON DBMS TO `privilegeShower`" +a|Rows: 1 +|=== + +[NOTE] +==== +Note that no specific privileges are required for showing the current user's privileges through the `SHOW USER _username_ PRIVILEGES` or `SHOW USER PRIVILEGES` commands. + +In addition, note that if a non-native auth provider like LDAP is in use, `SHOW USER PRIVILEGES` will only work with a limited capacity by making it only possible for a user to show their own privileges. +Other users' privileges cannot be listed when using a non-native auth provider. +==== + +The ability to assign privileges to roles can be granted via the `ASSIGN PRIVILEGE` privilege. +A user with this privilege is allowed to execute `GRANT` and `DENY` administration commands. +See an example of how to grant this privilege: + +[source, cypher, role=noplay] +---- +GRANT ASSIGN PRIVILEGE ON DBMS TO privilegeAssigner +---- + +The resulting role has privileges that only allow assigning privileges. +List all privileges for the role `privilegeAssigner` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE privilegeAssigner PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ASSIGN PRIVILEGE ON DBMS TO `privilegeAssigner`" +a|Rows: 1 +|=== + +The ability to remove privileges from roles can be granted via the `REMOVE PRIVILEGE` privilege. + +A user with this privilege is allowed to execute `REVOKE` administration commands. +See an example of how to grant this privilege: + +[source, cypher, role=noplay] +---- +GRANT REMOVE PRIVILEGE ON DBMS TO privilegeRemover +---- + +The resulting role has privileges that only allow removing privileges. +List all privileges for the role `privilegeRemover` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE privilegeRemover PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT REMOVE PRIVILEGE ON DBMS TO `privilegeRemover`" +a|Rows: 1 +|=== + +The privileges to list, assign, and remove privileges can be granted via the `PRIVILEGE MANAGEMENT` privilege. +See an example: + +[source, cypher, role=noplay] +---- +GRANT PRIVILEGE MANAGEMENT ON DBMS TO privilegeManager +---- + +The resulting role has all privileges to manage privileges. +List all privileges for the role `privilegeManager` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE privilegeManager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT PRIVILEGE MANAGEMENT ON DBMS TO `privilegeManager`" +a|Rows: 1 +|=== + + +[[access-control-dbms-administration-execute]] +== The DBMS `EXECUTE` privileges + +The DBMS privileges for procedure and user-defined function execution can be assigned by using Cypher administrative commands. +They can be granted, denied and revoked like other privileges. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.Execute privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command +| Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] EXECUTE PROCEDURE[S] name-globbing[, ...] + ON DBMS + TO role[, ...] +| Enables the specified roles to execute the given procedures. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] EXECUTE BOOSTED PROCEDURE[S] name-globbing[, ...] + ON DBMS + TO role[, ...] +| Enables the specified roles to use elevated privileges when executing the given procedures. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] EXECUTE ADMIN[ISTRATOR] PROCEDURES + ON DBMS + TO role[, ...] +| Enables the specified roles to execute procedures annotated with `@Admin`. The procedures are executed with elevated privileges. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] EXECUTE [USER [DEFINED]] FUNCTION[S] name-globbing[, ...] + ON DBMS + TO role[, ...] +| Enables the specified roles to execute the given user-defined functions. + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] EXECUTE BOOSTED [USER [DEFINED]] FUNCTION[S] name-globbing[, ...] + ON DBMS + TO role[, ...] +| Enables the specified roles to use elevated privileges when executing the given user-defined functions. +|=== + +[[access-control-execute-procedure]] +=== The `EXECUTE PROCEDURE` privilege + +The ability to execute a procedure can be granted via the `EXECUTE PROCEDURE` privilege. +A role with this privilege is allowed to execute the procedures matched by the <>. +The following query shows an example of how to grant this privilege: + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE db.schema.* ON DBMS TO procedureExecutor +---- + +Users with the role `procedureExecutor` can then run any procedure in the `db.schema` namespace. +The procedure is run using the user's own privileges. + +The resulting role has privileges that only allow executing procedures in the `db.schema` namespace. +List all privileges for the role `procedureExecutor` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE procedureExecutor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT EXECUTE PROCEDURE db.schema.* ON DBMS TO `procedureExecutor`" +a|Rows: 1 +|=== + +In order to allow the execution of all but only a few procedures, you can grant `EXECUTE PROCEDURES *` and deny the unwanted procedures. +For example, the following queries allow the execution of all procedures, except those starting with `dbms.cluster`: + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE * ON DBMS TO deniedProcedureExecutor +---- + +[source, cypher, role=noplay] +---- +DENY EXECUTE PROCEDURE dbms.cluster* ON DBMS TO deniedProcedureExecutor +---- + +The resulting role has privileges that only allow executing all procedures except those starting with `dbms.cluster`. +List all privileges for the role `deniedProcedureExecutor` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE deniedProcedureExecutor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY EXECUTE PROCEDURE dbms.cluster* ON DBMS TO `deniedProcedureExecutor`" +|"GRANT EXECUTE PROCEDURE * ON DBMS TO `deniedProcedureExecutor`" +a|Rows: 2 +|=== + + +The `dbms.cluster.checkConnectivity`, `dbms.cluster.cordonServer`, `dbms.cluster.protocols`, `dbms.cluster.readReplicaToggle`, `dbms.cluster.routing.getRoutingTable`, `dbms.cluster.secondaryReplicationDisable`, `dbms.cluster.setAutomaticallyEnableFreeServers`, and `dbms.cluster.uncordonServer` procedures are blocked, as well as any others starting with `dbms.cluster`. + + +[[access-control-execute-boosted-procedure]] +=== The `EXECUTE BOOSTED PROCEDURE` privilege + +The ability to use elevated privileges when executing a procedure can be granted via the `EXECUTE BOOSTED PROCEDURE` privilege. +A user with this privilege will not be restricted to their other privileges when executing the procedures matched by the <>. +The `EXECUTE BOOSTED PROCEDURE` privilege only affects the elevation, and not the execution of the procedure. +Therefore, it is needed to grant `EXECUTE PROCEDURE` privilege for the procedures as well. + + +[NOTE] +==== +Since Neo4j 5.0, both `EXECUTE PROCEDURE` and `EXECUTE BOOSTED PROCEDURE` are needed to execute a procedure with elevated privileges. +This differs from Neo4j 4.x, when only the `EXECUTE BOOSTED PROCEDURE` is required. +==== + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE * ON DBMS TO boostedProcedureExecutor; +GRANT EXECUTE BOOSTED PROCEDURE db.labels, db.relationshipTypes ON DBMS TO boostedProcedureExecutor +---- + +Users with the role `boostedProcedureExecutor` can thus run the `db.labels` and the `db.relationshipTypes` procedures with full privileges, seeing everything in the graph and not just the labels and types that the user has `TRAVERSE` privilege on. +Without the `EXECUTE PROCEDURE`, no procedures could be executed at all. + +The resulting role has privileges that allow executing the procedures `db.labels` and `db.relationshipTypes` with elevated privileges, and all other procedures with the user's own privileges: + +[source, cypher, role=noplay] +---- +SHOW ROLE boostedProcedureExecutor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT EXECUTE PROCEDURE * ON DBMS TO `boostedProcedureExecutor`" +|"GRANT EXECUTE BOOSTED PROCEDURE db.labels ON DBMS TO `boostedProcedureExecutor`" +|"GRANT EXECUTE BOOSTED PROCEDURE db.relationshipTypes ON DBMS TO `boostedProcedureExecutor`" +a|Rows: 3 +|=== + +As with grant, denying `EXECUTE BOOSTED PROCEDURE` on its own only affects the elevation and not the execution of the procedure. +This can be seen in the following examples: + +.Grant `EXECUTE PROCEDURE` and deny `EXECUTE BOOSTED PROCEDURE` +[example] +==== +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE * ON DBMS TO deniedBoostedProcedureExecutor1 +---- + +[source, cypher, role=noplay] +---- +DENY EXECUTE BOOSTED PROCEDURE db.labels ON DBMS TO deniedBoostedProcedureExecutor1 +---- + +The resulting role has privileges that allow the execution of all procedures using the user's own privileges. +It also prevents the `db.labels` procedure from being elevated. +Still, the denied `EXECUTE BOOSTED PROCEDURE` does not block execution of `db.labels`. + +To list all privileges for role `deniedBoostedProcedureExecutor1` as commands, use the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE deniedBoostedProcedureExecutor1 PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY EXECUTE BOOSTED PROCEDURE db.labels ON DBMS TO `deniedBoostedProcedureExecutor1`" +|"GRANT EXECUTE PROCEDURE * ON DBMS TO `deniedBoostedProcedureExecutor1`" +a|Rows: 2 +|=== +==== + +.Grant `EXECUTE BOOSTED PROCEDURE` and deny `EXECUTE PROCEDURE` +[example] +==== +[source, cypher, role=noplay] +---- +GRANT EXECUTE BOOSTED PROCEDURE * ON DBMS TO deniedBoostedProcedureExecutor2 +---- + +[source, cypher, role=noplay] +---- +DENY EXECUTE PROCEDURE db.labels ON DBMS TO deniedBoostedProcedureExecutor2 +---- + +The resulting role has privileges that allow elevating the privileges for all procedures, but cannot execute any due to missing or denied `EXECUTE PROCEDURE` privileges. +List all privileges for the role `deniedBoostedProcedureExecutor2` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE deniedBoostedProcedureExecutor2 PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY EXECUTE PROCEDURE db.labels ON DBMS TO `deniedBoostedProcedureExecutor2`" +|"GRANT EXECUTE BOOSTED PROCEDURE * ON DBMS TO `deniedBoostedProcedureExecutor2`" +a|Rows: 2 +|=== +==== + +.Grant `EXECUTE BOOSTED PROCEDURE` and deny `EXECUTE BOOSTED PROCEDURE` +[example] +==== +[source, cypher, role=noplay] +---- +GRANT EXECUTE BOOSTED PROCEDURE * ON DBMS TO deniedBoostedProcedureExecutor3 +---- + +[source, cypher, role=noplay] +---- +DENY EXECUTE BOOSTED PROCEDURE db.labels ON DBMS TO deniedBoostedProcedureExecutor3 +---- + +The resulting role has privileges that allow elevating the privileges for all procedures except `db.labels`, however no procedures can be executed due to missing `EXECUTE PROCEDURE` privilege. +List all privileges for the role `deniedBoostedProcedureExecutor3` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE deniedBoostedProcedureExecutor3 PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY EXECUTE BOOSTED PROCEDURE db.labels ON DBMS TO `deniedBoostedProcedureExecutor3`" +|"GRANT EXECUTE BOOSTED PROCEDURE * ON DBMS TO `deniedBoostedProcedureExecutor3`" +a|Rows: 2 +|=== +==== + +.How would the privileges from examples 1 to 3 affect the output of a procedure? +[example] +==== +Assume there is a procedure called `myProc`. + +This procedure gives the result `A` and `B` for a user with `EXECUTE PROCEDURE` privilege and `A`, `B` and `C` for a user with `EXECUTE BOOSTED PROCEDURE` privilege. + +Now, adapt the privileges from examples 1 to 3 to be applied to this procedure and show what is returned. +With the privileges from example 1, granted `EXECUTE PROCEDURE *` and denied `EXECUTE BOOSTED PROCEDURE myProc`, the `myProc` procedure returns the result `A` and `B`. + +With the privileges from example 2, granted `EXECUTE BOOSTED PROCEDURE *` and denied `EXECUTE PROCEDURE myProc`, execution of the `myProc` procedure is not allowed. + +With the privileges from example 3, granted `EXECUTE BOOSTED PROCEDURE *` and denied `EXECUTE BOOSTED PROCEDURE myProc`, execution of the `myProc` procedure is not allowed. + +For comparison, when granted: + +* `EXECUTE PROCEDURE myProc`: the `myProc` procedure returns the result `A` and `B`. +* `EXECUTE BOOSTED PROCEDURE myProc`: execution of the `myProc` procedure is not allowed. +* `EXECUTE PROCEDURE myProc` and `EXECUTE BOOSTED PROCEDURE myProc`: the `myProc` procedure returns the result `A`, `B`, and `C`. +==== + + +[[access-control-admin-procedure]] +=== The `EXECUTE ADMIN PROCEDURE` privilege + +The ability to execute admin procedures (annotated with `@Admin`) can be granted via the `EXECUTE ADMIN PROCEDURES` privilege. +This privilege is equivalent with granting the <> and <> privileges on each of the admin procedures. +Any newly added `admin` procedure is automatically included in this privilege. +The following query shows an example of how to grant this privilege: + +[source, cypher, role=noplay] +---- +GRANT EXECUTE ADMIN PROCEDURES ON DBMS TO adminProcedureExecutor +---- + +Users with the role `adminProcedureExecutor` can then run any `admin` procedure with elevated privileges. +The resulting role has privileges that allow the execution of all admin procedures. + +List all privileges for the role `adminProcedureExecutor` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE adminProcedureExecutor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT EXECUTE ADMIN PROCEDURES ON DBMS TO `adminProcedureExecutor`" +a|Rows: 1 +|=== + +In order to compare this with the `EXECUTE PROCEDURE` and `EXECUTE BOOSTED PROCEDURE` privileges, revisit the `myProc` procedure, but this time as an `admin` procedure, which will give the result `A`, `B` and `C` when allowed to execute. + +By starting with a user only granted the `EXECUTE PROCEDURE myProc` or the `EXECUTE BOOSTED PROCEDURE myProc` privilege, execution of the `myProc` procedure is not allowed. + +However, for a user granted the `EXECUTE ADMIN PROCEDURES` or both `EXECUTE PROCEDURE myProc` and `EXECUTE BOOSTED PROCEDURE myProc`, the `myProc` procedure returns the result `A`, `B` and `C`. + +Any denied `EXECUTE` privilege results in the procedure not being allowed to be executed. +In this case, it does not matter whether `EXECUTE PROCEDURE`, `EXECUTE BOOSTED PROCEDURE` or `EXECUTE ADMIN PROCEDURES` is being denied. + +[[access-control-execute-user-defined-function]] +=== The `EXECUTE USER DEFINED FUNCTION` privilege + +//EXECUTE [USER [DEFINED]] FUNCTION[S] +The ability to execute a user-defined function (UDF) can be granted via the `EXECUTE USER DEFINED FUNCTION` privilege. +A role with this privilege is allowed to execute the UDFs matched by the <>. + +[IMPORTANT] +==== +The `EXECUTE USER DEFINED FUNCTION` privilege does not apply to built-in functions, which are always executable. +==== + +.Execute user-defined function +====== +The following query shows an example of how to grant this privilege: + +[source,cypher,role=noplay] +---- +GRANT EXECUTE USER DEFINED FUNCTION apoc.coll.* ON DBMS TO functionExecutor +---- + +Or in short form: + +[source,cypher,role=noplay] +---- +GRANT EXECUTE FUNCTION apoc.coll.* ON DBMS TO functionExecutor +---- + +Users with the role `functionExecutor` can thus run any UDF in the `apoc.coll` namespace. +The function here is run using the user's own privileges. + +The resulting role has privileges that only allow executing UDFs in the `apoc.coll` namespace. +List all privileges for the role `functionExecutor` as commands by using the following query: + +[source,cypher,role=noplay] +---- +SHOW ROLE functionExecutor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT EXECUTE FUNCTION apoc.coll.* ON DBMS TO `functionExecutor`" +a|Rows: 1 +|=== +====== + +To allow the execution of all but a few UDFs, you can grant `+EXECUTE USER DEFINED FUNCTIONS *+` and deny the unwanted functions. + +.Execute user-defined functions +====== +The following queries allow the execution of all UDFs except those starting with `apoc.any.prop`: + +[source, cypher, role=noplay] +---- +GRANT EXECUTE USER DEFINED FUNCTIONS * ON DBMS TO deniedFunctionExecutor +---- + +[source, cypher, role=noplay] +---- +DENY EXECUTE USER DEFINED FUNCTION apoc.any.prop* ON DBMS TO deniedFunctionExecutor +---- + +Or in short form: + +[source, cypher, role=noplay] +---- +GRANT EXECUTE FUNCTIONS * ON DBMS TO deniedFunctionExecutor +---- + +[source, cypher, role=noplay] +---- +DENY EXECUTE FUNCTION apoc.any.prop* ON DBMS TO deniedFunctionExecutor +---- + +The resulting role has privileges that only allow the execution of all procedures except those starting with `apoc.any.prop`. +List all privileges for the role `deniedFunctionExecutor` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE deniedFunctionExecutor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY EXECUTE FUNCTION apoc.any.prop* ON DBMS TO `deniedFunctionExecutor`" +|"GRANT EXECUTE FUNCTION * ON DBMS TO `deniedFunctionExecutor`" +a|Rows: 2 +|=== + +The `apoc.any.property` and `apoc.any.properties` are blocked, as well as any other procedures starting with `apoc.any.prop`. +====== + +[[access-control-execute-boosted-user-defined-function]] +=== The `EXECUTE BOOSTED USER DEFINED FUNCTION` privilege + +//EXECUTE BOOSTED [USER [DEFINED]] FUNCTION[S] +The ability to use elevated privileges when executing a user-defined function (UDF) can be granted via the `EXECUTE BOOSTED USER DEFINED FUNCTION` privilege. +A user with this privilege will not be restricted to their other privileges when executing the UDFs matched by the <>. +The `EXECUTE BOOSTED USER DEFINED FUNCTION` privilege only affects the elevation and not the execution of the function. +Therefore, it is needed to grant `EXECUTE USER DEFINED FUNCTION` privilege for the functions as well. + + +[NOTE] +==== +Since Neo4j 5.0, both `EXECUTE USER DEFINED FUNCTION` and `EXECUTE BOOSTED USER DEFINED FUNCTION` are needed to execute a function with elevated privileges. +This differs from Neo4j 4.x, when only the `EXECUTE BOOSTED USER DEFINED FUNCTION` is required. +==== + +[IMPORTANT] +==== +The `EXECUTE BOOSTED USER DEFINED FUNCTION` privilege does not apply to built-in functions, as they have no concept of elevated privileges. +==== + +.Execute boosted user-defined function +====== +The following query shows an example of how to grant the `EXECUTE BOOSTED USER DEFINED FUNCTION` privilege: + +[source,cypher,role=noplay] +---- +GRANT EXECUTE USER DEFINED FUNCTION * ON DBMS TO boostedFunctionExecutor +GRANT EXECUTE BOOSTED USER DEFINED FUNCTION apoc.any.properties ON DBMS TO boostedFunctionExecutor +---- + +Or in short form: + +[source,cypher,role=noplay] +---- +GRANT EXECUTE FUNCTION * ON DBMS TO boostedFunctionExecutor +GRANT EXECUTE BOOSTED FUNCTION apoc.any.properties ON DBMS TO boostedFunctionExecutor +---- + +Users with the role `boostedFunctionExecutor` can thus run `apoc.any.properties` with full privileges and see every property on the node/relationship, not just the properties that the user has `READ` privilege on. +Without the `EXECUTE USER DEFINED FUNCTION` no UDFs could be executed at all. + +The resulting role has privileges that allow executing the UDF `apoc.any.properties` with elevated privileges, and all other UDFs with the users' own privileges. +List all privileges for the role `boostedFunctionExecutor` as commands by using the following query: + +[source,cypher,role=noplay] +---- +SHOW ROLE boostedFunctionExecutor PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer",width="100%",cols="m"] +|=== +|command +|"GRANT EXECUTE FUNCTION * ON DBMS TO `boostedFunctionExecutor`" +|"GRANT EXECUTE BOOSTED FUNCTION apoc.any.properties ON DBMS TO `boostedFunctionExecutor`" +a|Rows: 2 +|=== +====== + + +[role=label--new-5.6] +[[access-control-dbms-administration-setting]] +== The DBMS `SETTING` privileges + +The ability to show configuration settings can be granted via the `SHOW SETTING` privilege. +A role with this privilege is allowed to query the configuration settings matched by the <>. + + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +.Setting privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command +| Description + +| [source, syntax, role=noheader] +GRANT [IMMUTABLE] SHOW SETTING[S] name-globbing[, ...] + ON DBMS + TO role[, ...] +| Enables the specified roles to query given configuration settings. +|=== + +The following query shows an example of how to grant this privilege: + +[source, cypher, role=noplay] +---- +GRANT SHOW SETTING server.bolt.* ON DBMS TO configurationViewer +---- + +Users with the role `configurationViewer` can then query any setting in the `server.bolt` namespace. + +The updated role `configurationViewer` has privileges that only allow querying settings in the `server.bolt` namespace. +List all privileges for the role `configurationViewer` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE configurationViewer PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT SHOW SETTING server.bolt.* ON DBMS TO `configurationViewer`" +a|Rows: 1 +|=== + +To deny a specific setting from a role, first grant `SHOW SETTINGS *`, and then deny the unwanted setting. +For example, the following queries allow the querying of all settings, except those starting with `dbms.security`: + +[source, cypher, role=noplay] +---- +GRANT SHOW SETTINGS * ON DBMS TO deniedConfigurationViewer +---- + +[source, cypher, role=noplay] +---- +DENY SHOW SETTING dbms.security* ON DBMS TO deniedConfigurationViewer +---- + +The resulting role has privileges that allow querying all settings except those starting with `dbms.security`. +List all privileges for the role `deniedConfigurationViewer` as commands by using the following query: + +[source, cypher, role=noplay] +---- +SHOW ROLE deniedConfigurationViewer PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY SHOW SETTING dbms.security* ON DBMS TO `deniedConfigurationViewer`" +|"GRANT SHOW SETTING * ON DBMS TO `deniedConfigurationViewer`" +a|Rows: 2 +|=== + +As the query result shows, access to any setting starting with `dbms.security` are blocked, but the rest can still be queried. + + +[[access-control-dbms-administration-all]] +== Granting `ALL DBMS PRIVILEGES` + +The right to perform the following privileges can be achieved with a single command: + +* Create, drop, assign, remove, and show roles. +* Create, alter, drop, show, and impersonate users. +* Create, alter, and drop databases and aliases. +* Enable, alter, rename, reallocate, deallocate, and drop servers +* Show, assign, and remove privileges. +* Execute all procedures with elevated privileges. +* Execute all user-defined functions with elevated privileges. +* Show all configuration settings. + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +[source, syntax, role=noheader] +---- +GRANT [IMMUTABLE] ALL [[DBMS] PRIVILEGES] + ON DBMS + TO role[, ...] +---- + +For example, to grant the role `dbmsManager` the abilities above, use the following query: + +[source, cypher, role=noplay] +---- +GRANT ALL DBMS PRIVILEGES ON DBMS TO dbmsManager +---- + +The privileges granted can be seen using the `SHOW PRIVILEGES` command: + +[source, cypher, role=noplay] +---- +SHOW ROLE dbmsManager PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ALL DBMS PRIVILEGES ON DBMS TO `dbmsManager`" +a|Rows: 1 +|=== + +[[access-control-name-globbing]] +== Name-globbing for procedures, user-defined functions, and settings + +The name-globbing for procedures, user-defined functions, and setting names is a simplified version of globbing for filename expansions. +It only allows two wildcard characters: `+*+` and `?`, which are used for multiple and single-character matches. +In this case, `+*+` means 0 or more characters, and `?` matches exactly one character. + +[NOTE] +==== +The name-globbing is subject to the link:{neo4j-docs-base-uri}/cypher-manual/5/syntax/naming/[Cypher Manual -> Naming rules and recommendations], with the exception that it may include dots, stars, and question marks without the need for escaping using backticks. + +Each part of the name-globbing separated by dots may be individually quoted. +For example, `++mine.`procedureWith%`++` is allowed, but not `++mine.procedure`With%`++`. +Also, note that wildcard characters behave as wildcards even when quoted. +For example, using `++`*`++` is equivalent to using `+*+`, and thus allows executing all functions or procedures and not only the procedure or function named `+*+`. +==== + +Given the following list of procedures: + +* `mine.public.exampleProcedure` +* `mine.public.exampleProcedure1` +* `mine.public.exampleProcedure2` +* `mine.public.with#Special§Characters` +* `mine.private.exampleProcedure` +* `mine.private.exampleProcedure1` +* `mine.private.exampleProcedure2` +* `mine.private.with#Special§Characters` +* `your.exampleProcedure` + +The following examples demonstrate how name-globbing patterns can be used in controlling access to procedures. +Note that the same rules apply to user-defined functions and settings. + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE * ON DBMS TO globbing1 +---- + +Users with the role `globbing1` can run all the procedures. + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE mine.*.exampleProcedure ON DBMS TO globbing2 +---- + +Users with the role `globbing2` can run procedures `mine.public.exampleProcedure` and `mine.private.exampleProcedure`, but no other procedures. + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE mine.*.exampleProcedure? ON DBMS TO globbing3 +---- + +Users with the role `globbing3` can run procedures `mine.public.exampleProcedure1`, `mine.private.exampleProcedure1`, and `mine.private.exampleProcedure2`, but no other procedures. + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE *.exampleProcedure ON DBMS TO globbing4 +---- + +Users with the role `globbing4` can run procedures `your.exampleProcedure`, `mine.public.exampleProcedure`, and `mine.private.exampleProcedure`, but no other procedures. + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE mine.public.exampleProcedure* ON DBMS TO globbing5 +---- + +Users with the role `globbing5` can run procedures `mine.public.exampleProcedure`, `mine.public.exampleProcedure1` and `mine.public.exampleProcedure42`, but no other procedures. + +[source, cypher, role=noplay] +---- +GRANT EXECUTE PROCEDURE `mine.public.with#*§Characters`, mine.private.`with#Spec???§Characters` ON DBMS TO globbing6 +---- + +Users with the role `globbing6` can run procedures `mine.public.with#Special§Characters`, and `mine.private.with#Special§Characters`, but no other procedures. + +[NOTE] +==== +The name-globbing may be fully or partially quoted. +Both `+*+` and `+?+` are interpreted as wildcards in both cases. +==== + diff --git a/modules/ROOT/pages/authentication-authorization/immutable-roles-privileges.adoc b/modules/ROOT/pages/authentication-authorization/immutable-roles-privileges.adoc new file mode 100644 index 000000000..20b37a3a4 --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/immutable-roles-privileges.adoc @@ -0,0 +1,138 @@ +[role=enterprise-edition not-on-aura] +[[immutable-roles-and-privileges]] += Immutable roles and privileges +:description: This section explains how to use Cypher to manage immutable roles and privileges. + + +Immutable privileges are useful for restricting the actions of users who can themselves administer xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-privilege-management[privileges]. +Starting with Neo4j 5.26, Neo4j also introduces immutable roles. +Immutable roles are useful for providing _system roles_, which appear as permanent parts of the DBMS. + + +[CAUTION] +==== +Immutable privileges and roles should only be used in situations where changes are rare. +They are intentionally difficult to modify, so changes should be undertaken with caution (e.g., when the DBMS has been isolated by some other means and unauthorized access can be reliably prevented). +Typically, this type of modification should only be made once during the commissioning phase of a DBMS. +==== + +[[administer-immutable-roles-and-privileges]] +== Administer immutable roles and privileges + +After the DBMS is safely isolated from external connections, follow these steps to administer immutable roles and privileges: + +. Change the config setting xref:configuration/configuration-settings.adoc#config_dbms.security.auth_enabled[`dbms.security.auth_enabled`] to `false`. +. Restart the DBMS. +. Create or remove immutable privileges and roles in the same way as regular privileges and roles but with the addition of the `IMMUTABLE` keyword. +See <>. +. Change the config setting xref:configuration/configuration-settings.adoc#config_dbms.security.auth_enabled[`dbms.security.auth_enabled`] back to `true`. +. Restart the DBMS. + +Privileges and roles created in this way now appear as an immutable part of the DBMS. +If you want to change or remove them, you must repeat the process of setting xref:configuration/configuration-settings.adoc#config_dbms.security.auth_enabled[`dbms.security.auth_enabled`] to `false`. + +[[immutable-roles-privileges-examples]] +== Examples + +The following examples demonstrate how to use Cypher to manage immutable roles and privileges. + +=== Restricting the actions of users who can manage privileges + +To prevent all users (including those with `PRIVILEGE MANAGEMENT` privileges) from performing *database management*, attach an immutable privilege to the `PUBLIC` role. +The `PUBLIC` role implicitly and irrevocably applies to all users. + +. Ensure that you have completed steps 1 and 2 from <>. +. Run the following command to deny the `IMMUTABLE DATABASE MANAGEMENT` privilege to the `PUBLIC` role: ++ +[source, cypher, role=test-skip] +---- +DENY IMMUTABLE DATABASE MANAGEMENT ON DBMS TO PUBLIC +---- + +. Verify that the `IMMUTABLE` keyword has been added to the privilege: ++ +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES WHERE IMMUTABLE +---- ++ +.Result +[options="header,footer", width="100%", cols="1m,2m,1m,1m,1m,1m,1m"] +|=== +|access +|action +|resource +|graph +|segment +|role +|immutable + +|"DENIED" +|"database_management" +|"database" +|"*" +|"database" +|"PUBLIC" +|true + +7+a|Rows: 2 +|=== ++ +The result shows that all users are restricted from adding or removing privileges, including the `admin` user. +. Ensure you have completed steps 4 and 5 from <>. + +=== Creating permanent roles that cannot be changed + +You can use immutable roles to create permanent built-in system roles that cannot be modified even by users who have xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[`ROLE MANAGEMENT` privileges]. + +For example, you want to create an `analyst` role that cannot be dropped, renamed, or have any of its privileges changed (even by users with the `ROLE MANAGEMENT` and `PRIVILEGE MANAGEMENT` privileges). + + +. Ensure that you have completed steps 1 and 2 from <>. +. Create an immutable role to hold the immutable privileges: ++ +[source, cypher, role=noplay] +---- +CREATE IMMUTABLE ROLE analyst +---- + +. Immutably grant the `MATCH` privilege: ++ +[source, cypher, role=noplay] +---- +GRANT IMMUTABLE MATCH {*} ON GRAPH * ELEMENTS * TO analyst +---- + +. Ensure you have completed steps 4 and 5 from <>. ++ +Now, even users with `ROLE MANAGEMENT` and `PRIVILEGE MANAGEMENT` privileges will not be able do any of the following: ++ +.Drop the `analyst` role +[source, cypher, role=noplay] +---- +DROP ROLE analyst +---- ++ +.Revoke the `MATCH` privilege from the `analyst` role +[source, cypher, role=noplay] +---- +REVOKE MATCH {*} ON GRAPH * ELEMENTS * FROM analyst +---- ++ +.Rename the `analyst` role +[source, cypher, role=noplay] +---- +RENAME ROLE analyst TO dataReader +---- + +[NOTE] +==== +While the make-up (name, existence, associated privileges) of immutable roles is immutable, their assignment to users is not. +This means that an immutable role can itself be granted to or revoked from a user by any user with `ROLE MANAGEMENT` privileges. +==== +[NOTE] +==== +Only immutable privileges (e.g. `GRANT IMMUTABLE MATCH {*} ON GRAPH * ELEMENTS * TO analyst` in the example above) can be assigned to immutable roles. +This is to make sure that an immutable role and all of its privileges is explicitly and completely immutable. +==== + diff --git a/modules/ROOT/pages/authentication-authorization/index.adoc b/modules/ROOT/pages/authentication-authorization/index.adoc index c275e8a8a..3d9b570ff 100644 --- a/modules/ROOT/pages/authentication-authorization/index.adoc +++ b/modules/ROOT/pages/authentication-authorization/index.adoc @@ -1,24 +1,129 @@ [role=enterprise-edition] [[auth]] = Authentication and authorization -:description: This chapter describes authentication and authorization in Neo4j. +:description: An overview of authentication and authorization in Neo4j. +:keywords: authentication, authorization, security, access control, roles, privileges, users, LDAP, Active Directory, Kerberos, SSO, single sign-on, authentication plugins, authentication providers, native auth provider, LDAP auth provider, Kerberos auth provider, SSO auth provider, custom auth provider, custom auth plugin, custom auth plugins, custom auth providers, custom authentication plugin, custom authentication plugins, custom authentication providers, custom authorization plugin, custom authorization plugins, custom authorization providers, custom authorisation plugin, custom authorisation plugin +:page-aliases: authentication-authorization/introduction.adoc, authentication-authorization/terminology.adoc -This section helps you ensure that your Neo4j deployment adheres to your company's information security guidelines by setting up the appropriate authentication and authorization rules. +This page provides an overview of authentication and authorization in Neo4j. -The following topics are covered: +[[authentication-overview]] +== Authentication +Authentication is the process of verifying the identity of a user. +Neo4j has the following authentication (auth) providers that can perform user and role authentication: -* xref:authentication-authorization/introduction.adoc[Introduction] -* xref:authentication-authorization/built-in-roles.adoc[Built-in roles] -* xref:authentication-authorization/access-control.adoc[Fine-grained access control] -* xref:authentication-authorization/ldap-integration.adoc[Integration with LDAP directory services] -* xref:authentication-authorization/sso-integration.adoc[Integration with Single Sign-On (SSO) services] -* xref:authentication-authorization/manage-execute-permissions.adoc[Manage procedure and user-defined function permissions] -* xref:authentication-authorization/terminology.adoc[Terminology] +*Native auth provider*:: +Neo4j provides a native auth provider that stores user and role information in the `system` database. +The following parameters control this provider: ++ +==== +* xref:configuration/configuration-settings.adoc#config_dbms.security.auth_enabled[`dbms.security.auth_enabled`] (Default: `true`) -- Enable auth requirement to access Neo4j. + ++ +[NOTE] +If you need to disable authentication, make sure you block all network connections during the recovery phase so users can connect to Neo4j only via _localhost_. +This is necessary if, for example, you need to recover an `admin` user password or assign a user to the `admin` role. +For more information, see xref:authentication-authorization/password-and-user-recovery.adoc[Password and user recovery]. + +* xref:configuration/configuration-settings.adoc#config_dbms.security.auth_lock_time[`dbms.security.auth_lock_time`] (Default: `5s`) -- The amount of time a user account is locked after a configured number of unsuccessful authentication attempts. +* xref:configuration/configuration-settings.adoc#config_dbms.security.auth_max_failed_attempts[`dbms.security.auth_max_failed_attempts`] (Default: `3`) -- The maximum number of unsuccessful authentication attempts before imposing a user lock for a configured amount of time. + +When triggered, Neo4j logs an error containing a timestamp and the message `failed to log in: too many failed attempts` in the _security.log_. +==== ++ +For the relevant Cypher commands, see xref:authentication-authorization/manage-users.adoc#access-control-user-syntax[Manage users syntax], xref:authentication-authorization/manage-roles.adoc#access-control-role-syntax[Manage roles syntax], and xref:authentication-authorization/manage-privileges.adoc[Manage privileges syntax]. +Various scenarios that illustrate the use of the native auth provider are available in xref:tutorial/access-control.adoc[]. + +*User auth providers*:: +User auth providers allow you to link externally-defined users (e.g., in a third-party ID provider like OIDC or LDAP) to the Neo4j internal user model. +For more information, see xref:authentication-authorization/auth-providers.adoc[User auth providers]. + +*LDAP auth provider*:: +Controls authentication and authorization through external security software such as Active Directory or OpenLDAP, which is accessed via the built-in LDAP connector. +A description of the LDAP plugin using Active Directory is available in xref:authentication-authorization/ldap-integration.adoc[Integration with LDAP directory services]. + +*Single sign-on provider*:: +Integration with a single sign-on service, such as Okta, Auth0, or Microsoft Entra ID to provide centralized authentication and authorization for all your systems. +Neo4j supports the popular OpenID Connect mechanism for integrating with identity providers. +The configuration steps are described in xref:authentication-authorization/sso-integration.adoc[]. + +*Custom-built plugin auth providers*:: +A plugin option for building custom integrations. +It is recommended that this option is used as part of a custom delivery as negotiated with link:https://neo4j.com/professional-services/[Neo4j Professional Services]. +For more information, see link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/security-plugins[Java Reference -> Authentication and authorization plugins]. + +*Kerberos authentication and single sign-on*:: +In addition to LDAP, native, and custom providers, Neo4j supports Kerberos for authentication and single sign-on. +Kerberos support is provided via the link:{neo4j-docs-base-uri}/kerberos-add-on/current/[Neo4j Kerberos Add-On]. + +*Mixed-mode authentication*:: +Neo4j also supports mixed-mode authentication that allows you to use multiple authentication providers in your database setup. +For more information and examples, see xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-provider[Set Neo4j to use LDAP] and xref:authentication-authorization/sso-integration.adoc#auth-sso-configure-sso[Configure Neo4j to use OpenID Connect]. + + + + +[[authorization-overview]] +== Authorization + +Authorization is the process of determining whether a user is allowed to perform a specific action. +Authorization is managed using role-based access control (_RBAC_). +RBAC is a method of restricting access to authorized users. +It is a way of assigning privileges to roles that are then assigned to users. +This simplifies user management, as permissions are assigned to roles rather than to individual users. +The roles are defined in terms of their underlying _privileges_, and they can be modified by adding or removing these access rights using the Cypher commands described in this chapter. +Neo4j provides a set of xref:authentication-authorization/built-in-roles.adoc[built-in roles] and also allows you to create custom roles with specific privileges. +You can also use the _sub-graph_ access control, through which read access to the graph can be limited to specific combinations of labels, relationship types, and properties. [NOTE] --- -The functionality described in this section is applicable to Enterprise Edition. +==== +The functionality described in these pages applies to Enterprise Edition. A limited set of user management functions are also available in Community Edition. -xref:authentication-authorization/built-in-roles.adoc#auth-built-in-roles-overview[Native roles overview] gives a quick overview of these. --- \ No newline at end of file +xref:authentication-authorization/built-in-roles.adoc#auth-built-in-roles-overview[Built-in roles capabilities] gives a quick overview of these. +==== + +The Neo4j security model is stored in the system graph, which is maintained in the xref:database-administration/index.adoc#manage-databases-system[`system` database]. +All administrative commands need to be executed against it. +When connected to the DBMS over xref:configuration/connectors.adoc[], administrative commands are automatically routed to the `system` database. + +[[auth-terminology]] +== Terminology + +The following terms are relevant to role-based access control within Neo4j: + +[.compact] +[[term-active-user]]active user:: +A user who is active within the system and can perform actions prescribed by any assigned roles on the data. +This is in contrast to a suspended user. + +[[term-administrator]]administrator:: +This is a user who has been assigned the admin role. + +[[term-auth-provider]]auth provider:: +Properties attached to a user which define which authentication and authorization config to use for that user. + +[[term-authentication]]authentication:: +The process of verifying the identity of a user, typically using credentials like a username and password or a cryptographic token like a JWT. + +[[term-authorization]]authorization:: +The process of determining a user's access rights and privileges within Neo4j, based on their verified identity. + +[[term-current-user]]current user:: +This is the currently logged-in user invoking the commands. + +[[term-password-policy]]password policy:: +The password policy is a set of rules about what makes up a valid password. +For Neo4j, the following rules apply: +* The password cannot be an empty string. +* When changing passwords, the new password cannot be the same as the previous password. +* The password must be at least 8 characters long. + +[[term-role]]role:: +A collection of privileges that enables users to perform specific actions on the data. +A user can have multiple roles. + +[[term-suspended-user]]suspended user:: +A user who has been suspended is not able to access the database in any capacity, regardless of any assigned roles. + +[[term-user]]user:: +* A user is composed of a username and credentials, where the latter is a unit of information, such as a password, verifying the identity of a user. +* A user may represent a human, an application, etc. \ No newline at end of file diff --git a/modules/ROOT/pages/authentication-authorization/introduction.adoc b/modules/ROOT/pages/authentication-authorization/introduction.adoc deleted file mode 100644 index 4f46ed882..000000000 --- a/modules/ROOT/pages/authentication-authorization/introduction.adoc +++ /dev/null @@ -1,47 +0,0 @@ -[role=enterprise-edition] -[[auth-introduction]] -= Introduction -:description: This page provides an overview of authentication and authorization in Neo4j. - -This page provides an overview of authentication and authorization in Neo4j. -Authorization is managed using role-based access control (_RBAC_). -Permissions that define access control are assigned to roles, which are in turn assigned to users. - -Neo4j has the following auth providers, that can perform user authentication and authorization: - -*Native auth provider*:: -Neo4j provides a native auth provider that stores user and role information in the `system` database. -The following parameters control this provider: -+ -==== -* xref:reference/configuration-settings.adoc#config_dbms.security.auth_enabled[`dbms.security.auth_enabled`] (Default: `true`) -- Enable auth requirement to access Neo4j. + -+ -[NOTE] -If you need to disable authentication, for example, to recover an `admin` user password or assign a user to the `admin` role, make sure you block all network connections during the recovery phase so users can connect to Neo4j only via `localhost`. -For more information, see xref:configuration/password-and-user-recovery.adoc[Password and user recovery]. - -* xref:reference/configuration-settings.adoc#config_dbms.security.auth_lock_time[`dbms.security.auth_lock_time`] (Default: `5s`) -- The amount of time a user account is locked after a configured number of unsuccessful authentication attempts. -* xref:reference/configuration-settings.adoc#config_dbms.security.auth_max_failed_attempts[`dbms.security.auth_max_failed_attempts`] (Default: `3`) -- The maximum number of unsuccessful authentication attempts before imposing a user lock for a configured amount of time. + -When triggered, Neo4j logs an error containing a timestamp and the message `failed to log in: too many failed attempts` in the _security.log_. -==== -+ -The Cypher commands to manage users, roles, and permissions are described in detail in link:{neo4j-docs-base-uri}/cypher-manual/{neo4j-version}/access-control/[Cypher Manual -> Administration]. -Various scenarios that illustrate the use of the native auth provider are available in xref:authentication-authorization/access-control.adoc[Fine-grained access control]. - -*LDAP auth provider*:: -Another way of controlling authentication and authorization is through external security software such as Active Directory or OpenLDAP, which is accessed via the built-in LDAP connector. -A description of the LDAP plugin using Active Directory is available in xref:authentication-authorization/ldap-integration.adoc[Integration with LDAP directory services]. - -*Single Sign-On provider*:: -Some clients wish to centrally manage authentication and authorization for their systems in an identity provider which provides single sign-on for their other systems. -Neo4j supports the popular OpenID Connect mechanism for integrating with identity providers and configuration for that is described in xref:authentication-authorization/sso-integration.adoc[Integration with Single Sign-On Services]. - -*Custom-built plugin auth providers*:: -For clients with specific requirements not satisfied with either native or LDAP, Neo4j provides a plugin option for building custom integrations. -It is recommended that this option is used as part of a custom delivery as negotiated with Neo4j Professional Services. -The plugin is described in link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/security-plugins#extending-neo4j-security-plugins[Java Reference -> Authentication and authorization plugins]. - - -*Kerberos authentication and single sign-on*:: -In addition to LDAP, Native and custom providers, Neo4j supports Kerberos for authentication and single sign-on. -Kerberos support is provided via the link:{neo4j-docs-base-uri}/kerberos-add-on/current/[Neo4j Kerberos Add-On]. diff --git a/modules/ROOT/pages/authentication-authorization/ldap-integration.adoc b/modules/ROOT/pages/authentication-authorization/ldap-integration.adoc index 1dfd35a2c..213fd1fe4 100644 --- a/modules/ROOT/pages/authentication-authorization/ldap-integration.adoc +++ b/modules/ROOT/pages/authentication-authorization/ldap-integration.adoc @@ -1,42 +1,18 @@ [role=enterprise-edition] [[auth-ldap-integration]] -= Integration with LDAP directory services -:description: This page describes Neo4j support for integrating with LDAP systems. - -This page describes Neo4j support for integrating with LDAP systems. -The following topics are covered: - -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-introduction[Introduction] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-parameters[LDAP configuration parameters] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-provider[Set Neo4j to use LDAP] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-map-ldap-roles[Map the LDAP groups to the Neo4j roles] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-provider-ad[Configure Neo4j to use Active Directory] -** xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-provider-ad-uid[Configure Neo4j to support LDAP user ID authentication] -** xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-provider-ad-sysaccount[Configure Neo4j to support attribute authentication] -** xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-provider-ad-nosysaccount[Configure Neo4j to support `sAMAccountName` authentication by setting `user_dn_template`] -** xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-nested-groups[Configure Neo4j to perform nested group lookup] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-configure-provider-openldap[Configure Neo4j to use OpenLDAP] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-search[Verify the LDAP configuration] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-clear-auth-cache[The auth cache] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-ad-encrypted[Available methods of encryption] -** xref:authentication-authorization/ldap-integration.adoc#auth-ldap-encrypted-starttls[Use LDAP with encryption via StartTLS] -** xref:authentication-authorization/ldap-integration.adoc#auth-ldap-encrypted-ldaps[Use LDAP with encrypted LDAPS] -* xref:authentication-authorization/ldap-integration.adoc#auth-ldap-self-signed-certificate[Use a self-signed certificate (SSL) in a test environment] - - -[[auth-ldap-introduction]] -== Introduction += LDAP integration +:description: This page describes Neo4j support for integrating with LDAP systems. Neo4j supports LDAP, which allows for integration with Active Directory (AD), OpenLDAP, or other LDAP-compatible authentication services. This means that you use the LDAP service for managing federated users, while the native Neo4j user and role administration are completely turned off. The following configuration settings are important to consider when configuring LDAP. -For a more detailed overview of the LDAP configuration options, see xref:reference/configuration-settings.adoc[Configuration settings]. +For a more detailed overview of the LDAP configuration options, see xref:configuration/configuration-settings.adoc[Configuration settings]. [[auth-ldap-parameters]] == LDAP dynamic configuration settings -The following configuration settings can be updated while the database is running, see xref:configuration/dynamic-settings.adoc[Dynamic settings]. +The following configuration settings can be updated while the database is running, see xref:configuration/dynamic-settings.adoc[Update dynamic settings]. Altering any of these settings clears the authentication and authorization cache. [options="header",cols="<,<,<"] @@ -45,47 +21,51 @@ Altering any of these settings clears the authentication and authorization cache | Default value | Description -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authentication.user_dn_template[dbms.security.ldap.authentication.user_dn_template] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authentication.user_dn_template[dbms.security.ldap.authentication.user_dn_template] | `+uid={0},ou=users,dc=example,dc=com+` | Convert usernames into LDAP-specific fully qualified names required for logging in. -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authorization.user_search_base[dbms.security.ldap.authorization.user_search_base] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authorization.user_search_base[dbms.security.ldap.authorization.user_search_base] | `ou=users,dc=example,dc=com` | Set the base object or named context to search for user objects. -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authorization.user_search_filter[dbms.security.ldap.authorization.user_search_filter] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authorization.user_search_filter[dbms.security.ldap.authorization.user_search_filter] | `+(&(objectClass=*)(uid={0}))+` | Set an LDAP search filter for a user principal. -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authorization.group_membership_attributes[dbms.security.ldap.authorization.group_membership_attributes] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authorization.group_membership_attributes[dbms.security.ldap.authorization.group_membership_attributes] | `memberOf` | List attribute names of a user object that contains groups to be used for mapping to roles. Common values: `memberOf` and `gidNumber`. -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authorization.nested_groups_enabled[dbms.security.ldap.authorization.nested_groups_enabled] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authorization.nested_groups_enabled[dbms.security.ldap.authorization.nested_groups_enabled] | `false` -| This setting determines whether multiple LDAP search results will be processed. +| This setting determines whether multiple LDAP search results will be processed. This must be set to `true` in order to resolve nested group membership. -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authorization.group_to_role_mapping[dbms.security.ldap.authorization.group_to_role_mapping] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authorization.group_to_role_mapping[dbms.security.ldap.authorization.group_to_role_mapping] | | List an authorization mapping from groups to the pre-defined built-in roles `admin`, `architect`, `publisher`, `editor`, and `reader`, or to any other custom-defined roles. -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authentication.attribute[dbms.security.ldap.authentication.attribute] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authentication.attribute[dbms.security.ldap.authentication.attribute] | `samaccountname` | Set the attribute to search for users with a system account. -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authorization.access_permitted_group[dbms.security.ldap.authorization.access_permitted_group] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authorization.access_permitted_group[dbms.security.ldap.authorization.access_permitted_group] | | Set an LDAP group of users with access rights. Users passing authentication are mapped to at least the `PUBLIC` role in addition to any roles assigned by the xref:authentication-authorization/ldap-integration.adoc#auth-ldap-map-ldap-roles[group to role mapping] and have access to the database that those roles provide. If this attribute is set, users not part of this LDAP group will fail authentication, even if their credentials are correct. + +| xref:configuration/configuration-settings.adoc#config_dbms.security.logs.ldap.groups_at_debug_level_enabled[dbms.security.logs.ldap.groups_at_debug_level_enabled] +| `false` +| When set to `true`, it logs the result from the group lookup into the security log (provided the security log level is also set to `DEBUG`). |=== All settings are defined at server startup time in the default configuration file _xref:configuration/neo4j-conf.adoc[neo4j.conf]_ or can be modified at -runtime using xref:reference/procedures.adoc#procedure_dbms_setconfigvalue[`dbms.setConfigValue()`]. +runtime using xref:procedures.adoc#procedure_dbms_setConfigValue[`dbms.setConfigValue()`]. [[auth-ldap-configure-provider]] @@ -96,14 +76,28 @@ First, you configure Neo4j to use LDAP as an authentication and authorization pr . Uncomment the setting `dbms.security.auth_enabled=false` and change its value to `true` to turn on the security feature. . Uncomment the settings `dbms.security.authentication_providers` and `dbms.security.authorization_providers` and change their value to `ldap`. This way, the LDAP connector is used as a security provider for both authentication and authorization. ++ +If you want, you can still use the `native` provider for mixed-mode authentication and authorization. +The values are comma-separated and queried in the declared order. ++ +.Configure Neo4j to use LDAP and the native authentication and authorization provider +====== +[source,configuration,role="noheader"] +---- +dbms.security.authentication_providers=ldap,native +dbms.security.authorization_providers=ldap,native +---- +====== + [[auth-ldap-map-ldap-roles]] == Map the LDAP groups to the Neo4j roles -To access the user and role management procedures, you have to map the LDAP groups to the xref:authentication-authorization/built-in-roles.adoc[Neo4j built-in] and custom-defined roles. +To assign privileges to users based on their LDAP groups, you have to map the LDAP groups to the xref:authentication-authorization/built-in-roles.adoc[Neo4j built-in] and custom-defined roles. To do that, you need to know what privileges the Neo4j roles have, and based on these privileges, to create the mapping to the groups defined in the LDAP server. -The map must be formatted as a semicolon separated list of key-value pairs, where the key is a comma-separated list of the LDAP group names and the value is a comma-separated list of the corresponding role names. -For example, `group1=role1;group2=role2;group3=role3,role4,role5;group4,group5=role6`. +The map must be formatted as a semicolon separated list of key-value pairs, where the key is a LDAP group name and the value is a comma-separated list of the corresponding role names. + +For example, `group1=role1;group2=role2;group3=role3,role4,role5;group4=role6;group5=role6`. .Example of LDAP groups to Neo4j roles mapping ==== @@ -123,7 +117,7 @@ dbms.security.ldap.authorization.group_to_role_mapping=\ <3> Mapping of two LDAP groups to a Neo4j built-in role. <4> Mapping of an LDAP group to a custom-defined role. Custom-defined roles, such as `rolename`, must be explicitly created using the `CREATE ROLE rolename` command before they can be used to grant privileges. -See link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/manage-users[the Cypher Manual -> Creating roles]. +See xref:authentication-authorization/manage-roles.adoc[Manage roles]. ==== [[auth-ldap-configure-provider-ad]] @@ -204,7 +198,7 @@ dbms.security.ldap.authorization.system_username=cn=search-account,cn=Users,dc=e + [source, properties] ---- -dbms.security.ldap.authorization.system_password=mypassword +dbms.security.ldap.authorization.system_password=your_password ---- .. Configure which attribute to search for by adding the following lines to the _neo4j.conf_ file (replacing `myattribute` with the actual attribute name): @@ -258,10 +252,10 @@ The setting `dbms.security.ldap.authentication.search_for_attribute` should be s [[auth-ldap-configure-nested-groups]] === Configure Neo4j to perform nested group lookup -When a user is a member of a group (e.g. `engineers`) and that group is a member of another group (e.g. `employees`), Active Directory can be configured to perform a nested search such that a user in the group `engineers` would also be a member of the group `employees`. +When a user is a member of a group (e.g. `engineers`) and that group is a member of another group (e.g. `employees`), Active Directory can be configured to perform a nested search such that a user in the group `engineers` would also be a member of the group `employees`. This in turn means that it is possible to configure a xref:authentication-authorization/ldap-integration.adoc#auth-ldap-map-ldap-roles[group to role mapping] for `employees` which will transitively apply to `engineers`. -Active Directory facilitates nested search via the extensible match operator `LDAP_MATCHING_RULE_IN_CHAIN` (whose Object Identifier is 1.2.840.113556.1.4.1941). +Active Directory facilitates nested search via the extensible match operator `LDAP_MATCHING_RULE_IN_CHAIN` (whose Object Identifier is 1.2.840.113556.1.4.1941). This operator walks the chain of ancestry in objects all the way to the root. To set up nested search in the _neo4j.conf_ file, configure the following settings: @@ -283,7 +277,7 @@ dbms.security.ldap.authorization.user_search_filter=(&(objectClass=*)(uid={0})) ---- . Provide the nested groups search filter. + -This is the filter which will be used to perform the nested lookup of the user's groups. +This is the filter which will be used to perform the nested lookup of the user's groups. It should contain the placeholder token `{0}`, which will be substituted with the user's Distinguished Name (which is found for the specified user principle using `dbms.security.ldap.authorization.user_search_filter`). + This example features Active Directory's `LDAP_MATCHING_RULE_IN_CHAIN` (aka `1.2.840.113556.1.4.1941`) implementation: @@ -303,8 +297,8 @@ dbms.security.ldap.authorization.group_to_role_mapping=\ ---- [NOTE] -In contrast to a non-nested-LDAP lookup, a nested group lookup does not perform an attribute-based lookup on the user object. -Instead, the `dbms.security.ldap.authorization.group_membership_attributes` setting is ignored and the `dbms.security.ldap.authorization.user_search_filter` is only used to determine the Distinguished Name of the user. +In contrast to a non-nested-LDAP lookup, a nested group lookup does not perform an attribute-based lookup on the user object. +Instead, the `dbms.security.ldap.authorization.group_membership_attributes` setting is ignored and the `dbms.security.ldap.authorization.user_search_filter` is only used to determine the Distinguished Name of the user. This is then substituted into the `dbms.security.ldap.authorization.nested_groups_search_filter` to perform a separate, nested lookup of the user's groups. @@ -341,13 +335,143 @@ dbms.security.ldap.authorization.access_permitted_group=501 . Map the groups in the LDAP system to the Neo4j built-in and custom roles. For more information, see xref:authentication-authorization/ldap-integration.adoc#auth-ldap-map-ldap-roles[Map the LDAP groups to the Neo4j roles]. +[role=label--new-5.24] +[[auth-ldap-auth-providers]] +== Configure authentication/authorization at the user level using auth providers +xref:authentication-authorization/auth-providers.adoc[User auth providers] can be used to determine which users can authenticate and authorize using the configured providers, including LDAP. + +You must change the xref:configuration/configuration-settings.adoc#config_dbms.security.require_local_user[`dbms.security.require_local_user`] configuration setting to `true` to use auth providers. +This means that a user with a matching auth provider *must* exist in order to be able to authenticate and authorize. +This applies to all providers. + +Conversely, when xref:configuration/configuration-settings.adoc#config_dbms.security.require_local_user[`dbms.security.require_local_user`] is set to `false`, users' auth providers have no bearing on the way that they are authenticated and authorized, instead authentication and authorization is controlled centrally (for all users) by the database configuration. + +The following examples show how to configure users with auth provider `ldap` using Cypher. + +.Create a user with an auth provider who can authenticate and authorize using `LDAP` +====== +[source,cypher,role=noplay] +---- +CREATE USER alice +SET AUTH PROVIDER 'ldap' { SET ID 'cn=alice,ou=engineering,dc=example,dc=com' } +---- + +The command creates the user `alice` who can authenticate and authorize using LDAP provided their LDAP `dn` is `cn=alice,ou=engineering,dc=example,dc=com`. +====== + +.Create a user with two auth providers allowing the user to authenticate and authorize with either LDAP or the `mysso` provider +====== + +[source,cypher,role=noplay] +---- +CREATE USER alice +SET HOME DATABASE anotherDb +SET AUTH PROVIDER 'ldap' { SET ID 'cn=alice,ou=engineering,dc=example,dc=com' } +SET AUTH 'oidc-mysso' {SET ID 'alicesUniqueMySsoId'} +---- + +The command creates the user `alice` who can authenticate and authorize using `ldap` or `mysso`. +See xref:authentication-authorization/sso-integration.adoc#auth-sso-auth-providers[Configure SSO at the user level using auth providers] for more information on setting up an OIDC provider. +The example also illustrates that the user can have their home database set even when using only external auth providers. +====== + +.Alter a user to remove one of their auth providers +====== + +[source,cypher,role=noplay] +---- +ALTER USER alice +REMOVE AUTH 'ldap' +---- + +The command prevents the user `alice` from being able to authenticate and authorize using `ldap`. +====== + +.Alter a user to allow them to authenticate and authorize using username and password +====== + +[source,cypher,role=noplay] +---- +ALTER USER alice +SET AUTH 'native' {SET PASSWORD 'changeme' SET PASSWORD CHANGE REQUIRED} +---- + +The command allows the user `alice` to authenticate and authorize using the specified username and password (in addition to what they are already configured to use). +====== + + +.Configure the database to allow authentication via `ldap` and authorization via the `native` provider +====== + +. Set the following database config: ++ +[source, properties] +---- +dbms.security.authentication_providers=ldap +dbms.security.authorization_providers=native +---- + +. Create a user with an `ldap` auth provider: ++ +[source,cypher,role=noplay] +---- +CREATE USER alice +SET AUTH PROVIDER 'ldap' { SET ID 'cn=alice,ou=engineering,dc=example,dc=com' } +---- + +. Natively grant the `READER` role to the user: ++ +[source,cypher,role=noplay] +---- +GRANT ROLE READER TO alice +---- ++ +The command allows the user `alice` to authenticate using `ldap` and receive the `READER` role from the `native` provider. + +. You can also give the user the union of roles from `ldap` *and* `native` roles by setting `ldap` as an authorization provider too: ++ +[source, properties] +---- +dbms.security.authentication_providers=ldap +dbms.security.authorization_providers=native,ldap +---- +====== + +.Suspend a user +====== +[source,cypher,role=noplay] +---- +ALTER USER alice +SET STATUS SUSPENDED + +---- +The command completely prevents the user from being able to authenticate/authorize by any means. +====== + +.Disambiguate users with the same name in different LDAP trees +====== + +Suppose there are two users both with the name `alice`, one is part of the `engineering` tree (`cn=alice,ou=engineering,dc=example,dc=com`) and the other is part of the `sales` tree (`cn=alice,ou=sales,dc=example,dc=com`). + +To disambiguate these users, you can create two users in the database, each with a different `ID` that corresponds to the `dn` of the user in the LDAP tree. + +[source,cypher,role=noplay] +---- +CREATE USER aliceEngineering +SET AUTH 'ldap' { SET ID 'cn=alice,ou=engineering,dc=example,dc=com' } + +CREATE USER aliceSales +SET AUTH 'ldap' { SET ID 'cn=alice,ou=sales,dc=example,dc=com' } +---- +====== + [[auth-ldap-search]] == Verify the LDAP configuration You can verify that your LDAP configuration is correct, and that the LDAP server responds, by using the LDAP command-line tool `ldapsearch`. The `ldapsearch` command accepts the LDAP configuration setting values as input and verifies both the authentication (using the `simple` mechanism) and authorization of a user. -See the https://docs.ldap.com/ldap-sdk/docs/tool-usages/ldapsearch.html[ldapsearch official documentation^] for more advanced usage and how to use SASL authentication mechanisms. +See the link:https://docs.ldap.com/ldap-sdk/docs/tool-usages/ldapsearch.html[ldapsearch official documentation] for more advanced usage and how to use SASL authentication mechanisms. . Verify the authentication and authorization of a user. For example, `john`. @@ -367,7 +491,7 @@ ldapsearch -v -H ldap://myactivedirectory.example.com:389 -x -D cn=john,cn=Users ---- # ldapsearch -v -H ldap:// -x -D -w -b "" -ldapsearch -v -H ldap://myactivedirectory.example.com:389 -x -D cn=search-account,cn=Users,dc=example,dc=com -w mypassword -b cn=Users,dc=example,dc=com "(&(objectClass=*)(cn=john))" memberOf +ldapsearch -v -H ldap://myactivedirectory.example.com:389 -x -D cn=search-account,cn=Users,dc=example,dc=com -w your_password -b cn=Users,dc=example,dc=com "(&(objectClass=*)(cn=john))" memberOf ---- . Verify that the value of the returned membership attribute is a group that is mapped to a role in `dbms.security.ldap.authorization.group_to_role_mapping`. @@ -397,7 +521,7 @@ result: 0 Success [[auth-ldap-clear-auth-cache]] == The auth cache The _auth cache_ is the mechanism by which Neo4j caches the result of authentication via the LDAP server in order to aid performance. -It is configured with the parameters `xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authentication.cache_enabled[dbms.security.ldap.authentication.cache_enabled]`, and `xref:reference/configuration-settings.adoc#config_dbms.security.auth_cache_ttl[dbms.security.auth_cache_ttl]`. +It is configured with the parameters `xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authentication.cache_enabled[dbms.security.ldap.authentication.cache_enabled]`, and `xref:configuration/configuration-settings.adoc#config_dbms.security.auth_cache_ttl[dbms.security.auth_cache_ttl]`. [source, properties] ---- @@ -413,13 +537,13 @@ dbms.security.auth_cache_ttl=10m | Default value | Description -| xref:reference/configuration-settings.adoc#config_dbms.security.ldap.authentication.cache_enabled[dbms.security.ldap.authentication.cache_enabled] +| xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.authentication.cache_enabled[dbms.security.ldap.authentication.cache_enabled] | `true` | Determines whether or not to cache the result of authentication via the LDAP server. Whether authentication caching should be enabled or not must be considered in view of your company's security guidelines. -| xref:reference/configuration-settings.adoc#config_dbms.security.auth_cache_ttl[dbms.security.auth_cache_ttl] +| xref:configuration/configuration-settings.adoc#config_dbms.security.auth_cache_ttl[dbms.security.auth_cache_ttl] | `600 seconds` | Is the time to live (TTL) for cached authentication and authorization info. @@ -444,7 +568,7 @@ CALL dbms.security.clearAuthCache() [[auth-ldap-ad-encrypted]] == Available methods of encryption -Specifying the `xref:reference/configuration-settings.adoc#config_dbms.security.ldap.host[dbms.security.ldap.host]` parameter configures using LDAP without encryption. +Specifying the `xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.host[dbms.security.ldap.host]` parameter configures using LDAP without encryption. Not specifying the protocol or port results in `ldap` being used over the default port `389`. [source, properties] @@ -470,7 +594,7 @@ dbms.security.ldap.host=ldap://myactivedirectory.example.com [[auth-ldap-encrypted-ldaps]] === Use LDAP with encrypted LDAPS -To configure Active Directory with encrypted LDAPS, set `xref:reference/configuration-settings.adoc#config_dbms.security.ldap.host[dbms.security.ldap.host]` to one of the following. +To configure Active Directory with encrypted LDAPS, set `xref:configuration/configuration-settings.adoc#config_dbms.security.ldap.host[dbms.security.ldap.host]` to one of the following. If you do not specify the port, the default one `636` is used. [source, properties] @@ -495,3 +619,16 @@ server.jvm.additional=-Djavax.net.ssl.keyStorePassword=mypasword server.jvm.additional=-Djavax.net.ssl.trustStore=/path/to/MyCert.jks server.jvm.additional=-Djavax.net.ssl.trustStorePassword=mypasword ---- + +[[Auth-ldap-debug-group-result]] +== Debug logging of group result + +While setting up an LDAP integration, it is sometimes necessary to perform troubleshooting. +In these cases, it can be useful to view the group result from the LDAP server. +To enable the logging of these claims at `DEBUG` level in the security log, set xref:configuration/configuration-settings.adoc#config_dbms.security.logs.ldap.groups_at_debug_level_enabled[dbms.security.logs.ldap.groups_at_debug_level_enabled] to be `true` and the security log level to `DEBUG`. + +[WARNING] +==== +Make sure to set xref:configuration/configuration-settings.adoc#config_dbms.security.logs.ldap.groups_at_debug_level_enabled[dbms.security.logs.ldap.groups_at_debug_level_enabled] back to `false` for production environments to avoid unwanted logging of potentially sensitive information. +Also, bear in mind that the group result provided by the LDAP server can change over time. +==== diff --git a/modules/ROOT/pages/authentication-authorization/limitations.adoc b/modules/ROOT/pages/authentication-authorization/limitations.adoc new file mode 100644 index 000000000..9c31a473a --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/limitations.adoc @@ -0,0 +1,429 @@ +:description: Known limitations and implications of Neo4js role-based access control security. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated + +//// +[source, cypher, role=test-setup] +---- +CREATE ROLE users; +CREATE ROLE custom; +CREATE ROLE restricted; +CREATE ROLE unrestricted; +---- +//// + +[[access-control-limitations]] += Limitations + +The known limitations and implications of Neo4j's role-based access control security are described in this section. + +[[access-control-limitations-indexes]] +== Security and indexes + +As described in link:{neo4j-docs-base-uri}/cypher-manual/5/indexes-for-search-performance/[Cypher Manual -> Indexes for search performance], Neo4j {neo4j-version} supports the creation and use of indexes to improve the performance of Cypher queries. + +Note that the Neo4j security model impacts the results of queries, regardless if the indexes are used or not. +When using non full-text Neo4j indexes, a Cypher query will always return the same results it would have if no index existed. +This means that, if the security model causes fewer results to be returned due to restricted read access in xref:authentication-authorization/manage-privileges.adoc[Graph and sub-graph access control], +the index will also return the same fewer results. + +However, this rule is not fully obeyed by link:{neo4j-docs-base-uri}/cypher-manual/5/indexes-for-full-text-search[Cypher Manual -> Indexes for full-text search]. +These specific indexes are backed by _Lucene_ internally. +It is therefore not possible to know for certain whether a security violation has affected each specific entry returned from the index. +In face of this, Neo4j will return zero results from full-text indexes in case it is determined that any result might be violating the security privileges active for that query. + +Since full-text indexes are not automatically used by Cypher, they do not lead to the case where the same Cypher query would return different results simply because such an index was created. +Users need to explicitly call procedures to use these indexes. +The problem is only that, if this behavior is not known by the user, they might expect the full-text index to return the same results that a different, but semantically similar, Cypher query does. + +=== Example with denied properties + +Consider the following example. +The database has nodes with labels `:User` and `:Person`, and they have properties `name` and `surname`. +There are indexes on both properties: + +[source, cypher] +---- +CREATE INDEX singleProp FOR (n:User) ON (n.name); +CREATE INDEX composite FOR (n:User) ON (n.name, n.surname); +CREATE FULLTEXT INDEX userNames FOR (n:User|Person) ON EACH [n.name, n.surname]; +---- + +[NOTE] +==== +Full-text indexes support multiple labels. +See link:{neo4j-docs-base-uri}/cypher-manual/5/indexes-for-full-text-search/[Cypher Manual -> Indexes for full-text search] for more details on creating and using full-text indexes. +==== + +After creating these indexes, it would appear that the latter two indexes accomplish the same thing. +However, this is not completely accurate. +The composite and full-text indexes behave in different ways and are focused on different use cases. +A key difference is that full-text indexes are backed by _Lucene_, and will use the _Lucene_ syntax for querying. + +This has consequences for users restricted on the labels or properties involved in the indexes. +Ideally, if the labels and properties in the index are denied, they can correctly return zero results from both native indexes and full-text indexes. +However, there are borderline cases where this is not as simple. + +Imagine the following nodes were added to the database: + +[source, cypher] +---- +CREATE (:User {name: 'Sandy'}); +CREATE (:User {name: 'Mark', surname: 'Andy'}); +CREATE (:User {name: 'Andy', surname: 'Anderson'}); +CREATE (:User:Person {name: 'Mandy', surname: 'Smith'}); +CREATE (:User:Person {name: 'Joe', surname: 'Andy'}); +---- + +Consider denying the label `:Person`: + +[source, cypher] +---- +DENY TRAVERSE ON GRAPH * NODES Person TO users +---- + +If the user runs a query that uses the native single property index on `name`: + +[source, cypher] +---- +MATCH (n:User) WHERE n.name CONTAINS 'ndy' RETURN n.name +---- + +This query performs several checks: + +* Scans the index to create a stream of results of nodes with the `name` property, which leads to five results. +* Filters the results to include only nodes where `n.name CONTAINS 'ndy'`, filtering out `Mark` and `Joe`, which leads to three results. +* Filters the results to exclude nodes that also have the denied label `:Person`, filtering out `Mandy`, which leads to two results. + +Two results will be returned from this dataset and only one of them has the `surname` property. + +In order to use the native composite index on `name` and `surname`, the query needs to include a predicate on the `surname` property as well: + +[source, cypher] +---- +MATCH (n:User) +WHERE n.name CONTAINS 'ndy' AND n.surname IS NOT NULL +RETURN n.name +---- + +This query performs several checks, which are almost identical to the single property index query: + +* Scans the index to create a stream of results of nodes with the `name` and `surname` property, which leads to four results. +* Filters the results to include only nodes where `n.name CONTAINS 'ndy'`, filtering out `Mark` and `Joe`, which leads to two results. +* Filters the results to exclude nodes that also have the denied label `:Person`, filtering out `Mandy`, which leads to only one result. + +Only one result was returned from the above dataset. +What if this query with the full-text index was used instead: + +[source, cypher] +---- +CALL db.index.fulltext.queryNodes("userNames", "ndy") YIELD node, score +RETURN node.name +---- + +The problem now is that it is not certain whether the results provided by the index were achieved due to a match to the `name` or the `surname` property. +The steps taken by the query engine would be: + +* Run a _Lucene_ query on the full-text index to produce results containing `ndy` in either property, leading to five results. +* Filter the results to exclude nodes that also have the label `:Person`, filtering out `Mandy` and `Joe`, leading to three results. + +This difference in results is caused by the `OR` relationship between the two properties in the index creation. + +=== Denying properties + +Now consider denying access on properties, like the `surname` property: + +[source, cypher] +---- +DENY READ {surname} ON GRAPH * TO users +---- + +For that, run the same queries again: + +[source, cypher] +---- +MATCH (n:User) +WHERE n.name CONTAINS 'ndy' +RETURN n.name +---- + +This query operates exactly as before, returning the same two results, because nothing in it relates to the denied property. + +However, this is not the same for the query targeting the composite index: + +[source, cypher] +---- +MATCH (n:User) +WHERE n.name CONTAINS 'ndy' AND n.surname IS NOT NULL +RETURN n.name +---- + +Since the `surname` property is denied, it will appear to always be `null` and the composite index empty. Therefore, the query returns no result. + +Now consider the full-text index query: + +[source, cypher] +---- +CALL db.index.fulltext.queryNodes("userNames", "ndy") YIELD node, score +RETURN node.name +---- + +The problem remains, since it is not certain whether the results provided by the index were returned due to a match on the `name` or the `surname` property. +Results from the `surname` property now need to be excluded by the security rules, because they require that the user is unable to see any `surname` properties. +However, the security model is not able to introspect the _Lucene_ query in order to know what it will actually do, whether it works only on the allowed `name` property, or also on the disallowed `surname` property. +What is known is that the earlier query returned a match for `Joe Andy` which should now be filtered out. +Therefore, in order to never return results the user should not be able to see, all results need to be blocked. +The steps taken by the query engine would be: + +* Determine if the full-text index includes denied properties. +* If yes, return an empty results stream. +Otherwise, it will process as described before. + +In this case, the query will return zero results rather than simply returning the results `Andy` and `Sandy`, which might have been expected. + + +[[access-control-limitations-labels]] +== Security and labels + +=== Traversing the graph with multi-labeled nodes + +The general influence of access control privileges on graph traversal is described in detail in xref:authentication-authorization/manage-privileges.adoc[Graph and sub-graph access control]. +The following section will only focus on nodes due to their ability to have multiple labels. +Relationships can only have one type of label and thus they do not exhibit the behavior this section aims to clarify. +While this section will not mention relationships further, the general function of the traverse privilege also applies to them. + +For any node that is traversable, due to `GRANT TRAVERSE` or `GRANT MATCH`, +the user can get information about the attached labels by calling the built-in `labels()` function. +In the case of nodes with multiple labels, they can be returned to users that weren't directly granted access to. + +To give an illustrative example, imagine a graph with three nodes: one labeled `:A`, another labeled `:B` and one with the labels `:A` and `:B`. +In this case, there is a user with the role `custom` defined by: + +[source, cypher] +---- +GRANT TRAVERSE ON GRAPH * NODES A TO custom +---- + +If that user were to execute + +[source, cypher] +---- +MATCH (n:A) +RETURN n, labels(n) +---- + +They would get a result with two nodes: the node that was labeled with `:A` and the node with labels `:A :B`. + +In contrast, executing + +[source, cypher] +---- +MATCH (n:B) +RETURN n, labels(n) +---- + +This will return only the one node that has both labels: `:A` and `:B`. +Even though `:B` did not have access to traversals, there is one node with that label accessible in the dataset due to the allow-listed label `:A` that is attached to the same node. + +If a user is denied to traverse on a label they will never get results from any node that has this label attached to it. +Thus, the label name will never show up for them. +As an example, this can be done by executing: + +[source, cypher] +---- +DENY TRAVERSE ON GRAPH * NODES B TO custom +---- + +The query + +[source, cypher] +---- +MATCH (n:A) +RETURN n, labels(n) +---- + +will now return the node only labeled with `:A`, while the query + +[source, cypher] +---- +MATCH (n:B) +RETURN n, labels(n) +---- + +will now return no nodes. + +=== The db.labels() procedure + +In contrast to the normal graph traversal described in the previous section, the built-in `db.labels()` procedure is not processing the data graph itself, but the security rules defined on the system graph. +That means: + +* If a label is explicitly whitelisted (granted), it will be returned by this procedure. +* If a label is denied or isn't explicitly allowed, it will not be returned by this procedure. + +Reusing the previous example, imagine a graph with three nodes: one labeled `:A`, another labeled `:B` and one with the labels `:A` and `:B`. +In this case, there is a user with the role `custom` defined by: + +[source, cypher] +---- +GRANT TRAVERSE ON GRAPH * NODES A TO custom +---- + +This means that only label `:A` is explicitly allow-listed. +Thus, executing + +[source, cypher] +---- +CALL db.labels() +---- + +will only return label `:A`, because that is the only label for which traversal was granted. + +[[access-control-limitations-non-existing-labels]] +=== Privileges for non-existing labels, relationship types, and property names + +Privileges for non-existent labels, relationship types, and property names have an effect only once the latter are created. +In other words, when authorizing a user, only privileges for existing labels, relationship types, and property names are applied. +This is because the graph elements must be resolved internally to be able to check against the privileges when users try to use them later. +If a label, relationship type, or property name does not yet exist, it will not resolve, and therefore, the privileges will not apply. + +A way around this is to create the label, relationship type, or property name using the `db.createLabel()`, `db.createRelationshipType()`, and `db.createProperty()` procedures on the relevant database when creating the privileges. + +Labels, relationship types, and property names are considered non-existent in a database if: + +* There has never been a node with that label, a relationship with that relationship type, or a property with that name. +* There has been no attempt to add a node with that label, a relationship with that relationship type, or a property with that name. + +The attempted creation adds it to the known labels, relationship types, and property names even if the creation itself fails (unless it fails on missing or denied privileges to create new labels, relationship types, or property names). +* They have not been created using any of the `db.createLabel()`, `db.createRelationshipType()`, or `db.createProperty()` procedures. + +There is currently no way to remove a label, relationship type, or property name from the database. +Once existent in the database, they cannot return to non-existent. + +For example, let's assume that you have a new, freshly-created empty database, called `testing`, and a user named `Alice` with a `custom` role. +[NOTE] +===== +The example focuses only on nodes and their labels, though the same principle applies to relationships and their relationship type, and properties (on both nodes and relationships) and their names. +===== + +Using the following command, you define some privileges to the `custom` role: +[source, cypher] +---- +GRANT MATCH {*} ON GRAPH testing NODES * TO custom +GRANT CREATE ON GRAPH testing NODES `A` TO custom +GRANT SET LABEL `A` ON GRAPH testing TO custom +GRANT CREATE NEW NODE LABEL ON DATABASE testing TO custom +---- + +This means that when `Alice` executes: + +[source, cypher] +---- +CREATE (:`A`) +---- + +She will get the following exception even though she is allowed to create new labels: +[source] +---- +Create node with labels 'A' on database 'testing' is not allowed for user 'Alice' with roles [PUBLIC, custom]. +---- + +However, rerunning the same query will create the node. +This is because the failed creation still creates the label, making it no longer non-existent when the query is run a second time. + +To ensure success on the first attempt, when setting up the privileges for the `custom` role, the administrator should run the `db.createLabel()` procedure on the affected databases for all non-existing labels that get assigned privileges. +In this example, when creating the custom role, connect to `testing` and run `CALL db.createLabel('A')` to ensure Alice creates the node successfully on her first attempt. + + + +[[access-control-limitations-db-operations]] +== Security and performance + +The rules of a security model may impact the performance of some database operations. +This is because extra security checks are necessary, and they require additional data access. +For example, count store operations, which are usually fast lookups, may experience notable differences in performance. + +The following example shows how the database behaves when adding security rules to roles `restricted` and `unrestricted`: + +[source, cypher] +---- +GRANT TRAVERSE ON GRAPH * NODES Person TO restricted; +DENY TRAVERSE ON GRAPH * NODES Customer TO restricted; +GRANT TRAVERSE ON GRAPH * ELEMENTS * TO unrestricted; +---- + +Now, let's look at what the database needs to do in order to execute the following query: + +[source, cypher] +---- +MATCH (n:Person) +RETURN count(n) +---- + +For both roles, the execution plan looks like this: + +---- ++--------------------------+ +| Operator | ++--------------------------+ +| +ProduceResults | +| | + +| +NodeCountFromCountStore | ++--------------------------+ +---- + +Internally, however, very different operations need to be executed. +The following table illustrates the difference: + +[%header,cols=2*] +|=== +|User with `unrestricted` role +|User with `restricted` role + +|The database can access the count store and retrieve the total number of nodes with the label `:Person`. + +This is a very quick operation. + +|The database cannot access the count store because it must make sure that only traversable nodes with the desired label `:Person` are counted. +Due to this, each node with the `:Person` label needs to be accessed and examined to make sure that they do not have a deny-listed label, such as `:Customer`. + +So due to the additional data access required by the security checks, this operation will be slower compared to executing the query as an unrestricted user. + +|=== + +[[property-based-access-control-limitations]] +=== Property-based access control limitations +Extra node-level security checks are necessary when adding security rules based on property rules, and these can have a significant performance impact. +The following example shows how the database behaves when adding security rules to roles `restricted` and `unrestricted`: + +[source, cypher] +---- +GRANT TRAVERSE ON GRAPH * FOR (n:Customer) WHERE n.secret <> true TO restricted; +GRANT TRAVERSE ON GRAPH * ELEMENTS * TO unrestricted; +---- + +When executing query: + +[source, cypher] +---- +MATCH (n:Customer) +RETURN n +---- +For both roles, the execution plan looks like this: +---- ++--------------------------+ +| Operator | ++--------------------------+ +| +ProduceResults | +| | + +| +AllNodesScan | ++--------------------------+ +---- +Internally, however, very different operations need to be executed. +The following table illustrates the difference: +[%header,cols=2*] +|=== +|User with `unrestricted` role +|User with `restricted` role +|The database will scan all nodes and quickly identify accessible nodes based solely on the presence of the `:Customer` label. +This is a relatively quick operation. +|The database will scan all nodes, identify potentially accessible nodes based on the presence of the specified label, and then also access the properties of each of those nodes and inspect their values to ensure the property rule criteria are met (i.e., that `secret` is not set to `true` in this case). +So due to the additional data access required by the security checks, this operation will be slower compared to executing the query as an unrestricted user. +|=== \ No newline at end of file diff --git a/modules/ROOT/pages/authentication-authorization/load-privileges.adoc b/modules/ROOT/pages/authentication-authorization/load-privileges.adoc new file mode 100644 index 000000000..11c4a76e7 --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/load-privileges.adoc @@ -0,0 +1,134 @@ +:description: How to use Cypher to manage load privileges. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated +//// +[source, cypher, role=test-setup] +---- +CREATE ROLE roleLoadAllData +CREATE ROLE roleLoadCidr +---- +//// + +[[access-control-load-privileges]] += Load privileges + +_This feature is available from Neo4j 5.13._ + +This section explains how to use Cypher to manage load privileges. +All load privileges apply to the whole system. +Like DBMS privileges, they do not belong to one specific database or graph. +For more details on the differences between graphs, databases, and the DBMS, refer to link:{neo4j-docs-base-uri}/cypher-manual/5/introduction/cypher_neo4j/[Cypher Manual -> Cypher and Neo4j]. + +image::privileges_grant_and_deny_syntax_load_privileges.svg[width="800", title="Syntax of GRANT and DENY load Privileges"] + +// TODO: add image later when there is more than one LOAD privilege +//image::privileges_hierarchy_load.svg[title="Load privileges hierarchy"] + +The load privileges apply to the Cypher link:{neo4j-docs-base-uri}/cypher-manual/5/clauses/load-csv/[`LOAD CSV` clause], deciding whether or not the data can be loaded from the given source. + +== Load privileges syntax + +The load privileges are assigned using Cypher administrative commands. +They can be granted, denied, and revoked in the same way as other privileges. +For more details, see xref:authentication-authorization/manage-privileges.adoc[RBAC and fine-grained privileges]. + +.Load privileges command syntax +[options="header", width="100%", cols="3a,2"] +|=== +| Command | Description + +| [source, syntax] +GRANT [IMMUTABLE] LOAD + ON ALL DATA + TO role[, ...] +| Enables the specified roles to load external data in queries. + +| [source, syntax] +GRANT [IMMUTABLE] LOAD + ON CIDR cidr + TO role[, ...] +| Enables the specified roles to load external data from the given CIDR range in queries.label:new[Introduced in 5.16] + +|=== + +[NOTE] +==== +More details about the syntax descriptions can be found xref:database-administration/syntax.adoc[Cypher syntax for administration commands]. +==== + +Unlike other privileges, the `LOAD` privilege is not granted, denied, or revoked on `DBMS`, `DATABASE`, or `GRAPH`, but instead on the data source to load from. +Adding `ON ALL DATA` means a role has the privilege to load data from all sources. +To only allow loading data from sources given by a specific CIDR range use `ON CIDR cidr`. + +[IMPORTANT] +==== +It is strongly recommended to permit resource loading only over secure protocols such as HTTPS instead of insecure protocols like HTTP. +This can be done by limiting the accessible ranges to only trusted sources that use secure protocols. +If allowing an insecure protocol is absolutely unavoidable, Neo4j takes measures internally to enhance the security of these requests within their limitations. +However, this means that insecure URLs on virtual hosts will not function unless you add the JVM argument `-Dsun.net.http.allowRestrictedHeaders=true` to the configuration setting xref:configuration/configuration-settings.adoc#config_server.jvm.additional[`server.jvm.additional`]. +==== + +[[access-control-load-all-data]] +== The `ALL DATA` privilege + +The load privilege on `ALL DATA` enables or disables loading data. +If granted, the user can load data from any source. +If missing or denied, no data can be loaded at all. + +.Grant users with the role `roleLoadAllData` the ability to load data with `LOAD CSV` +==== +[source, cypher] +---- +GRANT LOAD ON ALL DATA TO roleLoadAllData +---- +==== + +.List all privileges for the role `roleLoadAllData` as commands +==== +[source, cypher] +---- +SHOW ROLE roleLoadAllData PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT LOAD ON ALL DATA TO `roleLoadAllData`" +a|Rows: 1 +|=== +==== + +The `LOAD ON ALL DATA` privilege is granted to the `PUBLIC` role by default. + +[[access-control-load-cidr]] +== The `CIDR` privilege + +_This feature is available from Neo4j 5.16._ + +The load privilege on `CIDR cidr` enables or disables loading data from the given IPv4 or IPv6 CIDR range. +If granted, the user can load data from sources in the given CIDR range. +If missing or denied, no data can be loaded from sources in the given CIDR range. + +.Denies users with the role `roleLoadCidr` the ability to load data with `LOAD CSV` from `127.0.0.1/32` +==== +[source, cypher] +---- +DENY LOAD ON CIDR "127.0.0.1/32" TO roleLoadCidr +---- +==== + +.List all privileges for the role `roleLoadCidr` as commands +==== +[source, cypher] +---- +SHOW ROLE roleLoadCidr PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY LOAD ON CIDR "127.0.0.1/32" TO `roleLoadCidr`" +a|Rows: 1 +|=== +==== \ No newline at end of file diff --git a/modules/ROOT/pages/authentication-authorization/manage-execute-permissions.adoc b/modules/ROOT/pages/authentication-authorization/manage-execute-permissions.adoc index cf22f8ca5..f21e47852 100644 --- a/modules/ROOT/pages/authentication-authorization/manage-execute-permissions.adoc +++ b/modules/ROOT/pages/authentication-authorization/manage-execute-permissions.adoc @@ -1,35 +1,35 @@ [role=enterprise-edition] [[auth-manage-execute-permissions]] -= Manage procedure and user-defined function permissions -:description: This section describes how access control works with procedures and user-defined functions in Neo4j. += Procedure and user-defined function privileges +:description: This section describes how access control works with procedures and user-defined functions in Neo4j. To be able to run a procedure or user-defined function, the user needs to have the corresponding execute privilege. Procedures and user-defined functions are executed according to the same security rules as regular Cypher statements, e.g. a procedure performing writes will fail if called by a user that only has _read_ privileges. -Procedures and user-defined functions can also be run with privileges exceeding the users own privileges. +Procedures and user-defined functions can also be run with privileges exceeding the users' own privileges. This is called _execution boosting_. -The elevated privileges only apply within the procedure or user-defined function; any operation performed outside will still use the users original privileges. +The elevated privileges only apply within the procedure or user-defined function; any operation performed outside will still use the users' original privileges. [NOTE] -- The steps below assume that the procedure or user-defined function is already developed and installed. -Please refer to link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j#extending-neo4j[Java Reference -> Extending Neo4j] for a description on creating and using user-defined procedures and functions. +Please refer to link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/[Java Reference -> Extending Neo4j] for a description of creating and using user-defined procedures and functions. -- [[auth-manage-procedure-permissions]] == Manage procedure permissions -Procedure permissions can be managed using the link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-dbms-administration-execute[native execute privileges]. -These control whether the user is allowed to both execute a procedure, and which set of privileges apply during the execution. +Procedure permissions can be managed using the xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-execute[native execute privileges]. +These control whether the user is allowed to execute a procedure and which set of privileges apply during the execution. -A procedure may be run using the link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-execute-procedure[`EXECUTE PROCEDURE` privilege]. +A procedure may be run using the xref:authentication-authorization/dbms-administration.adoc#access-control-execute-procedure[`EXECUTE PROCEDURE` privilege]. -This allows the user to execute procedures that match the link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-name-globbing[globbed procedures]. +This allows the user to execute procedures that match the xref:authentication-authorization/dbms-administration.adoc#access-control-name-globbing[globbed procedures]. -.Grant privilege to execute procedure +.Grant privilege to execute a procedure ==== [source, cypher] ---- @@ -37,7 +37,7 @@ GRANT EXECUTE PROCEDURE db.schema.visualization ON DBMS TO visualizer ---- This will allow any user with the `visualizer` role to execute the `db.schema.visualization`. -E.g. a user that also have the following privileges: +E.g. a user that also has the following privileges: [source, cypher] ---- @@ -45,10 +45,10 @@ GRANT TRAVERSE ON GRAPH * NODES A, B TO role GRANT TRAVERSE ON GRAPH * RELATIONSHIP R1 TO role ---- -When calling the `db.schema.visualization` procedure that user will only see the `A` and `B` nodes and `R1` relationships, even though there might exist other nodes and relationships. +When calling the `db.schema.visualization` procedure, the user will only see the `A` and `B` nodes and `R1` relationships, even though there might exist other nodes and relationships. ==== -A procedure may also be executed with elevated privileges using the link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-execute-boosted-procedure[`EXECUTE BOOSTED PROCEDURE` privilege]. +A procedure may also be executed with elevated privileges using the xref:authentication-authorization/dbms-administration.adoc#access-control-execute-boosted-procedure[`EXECUTE BOOSTED PROCEDURE` privilege]. [NOTE] -- @@ -67,21 +67,21 @@ GRANT EXECUTE BOOSTED PROCEDURE db.schema.visualization ON DBMS TO visualizer ---- This will allow any user with the `visualizer` role to execute the `db.schema.visualization` with elevated privileges. -When calling the `db.schema.visualization` procedure that user will see all nodes and relationships that exist in the graph, even though they have no traversal privileges. +When calling the `db.schema.visualization` procedure, the user will see all nodes and relationships that exist in the graph, even though they have no traversal privileges. ==== [[auth-manage-function-permissions]] == Manage user-defined function permissions -User-defined function permissions can be managed using the link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-dbms-administration-execute[native execute privileges]. -These control if the user is both allowed to execute a user-defined function, and which set of privileges apply during the execution. +User-defined function permissions can be managed using the xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-execute[native execute privileges]. +These control if the user is both allowed to execute a user-defined function and which set of privileges apply during the execution. -A user-defined function may be executed using the link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-execute-user-defined-function[`EXECUTE USER DEFINED FUNCTION` privilege]. +A user-defined function may be executed using the xref:authentication-authorization/dbms-administration.adoc#access-control-execute-user-defined-function[`EXECUTE USER DEFINED FUNCTION` privilege]. -This allows the user to execute user-defined functions that match the link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-name-globbing[globbed user-defined function]. +This allows the user to execute user-defined functions that match the xref:authentication-authorization/dbms-administration.adoc#access-control-name-globbing[globbed user-defined function]. -.Grant privilege to execute user-defined function +.Grant privilege to execute a user-defined function ==== [source, cypher] ---- @@ -89,7 +89,7 @@ GRANT EXECUTE USER DEFINED FUNCTION apoc.any.properties ON DBMS TO custom ---- This will allow any user with the `custom` role to execute the `apoc.any.properties`. -E.g. a user that also have the following privilege: +E.g. a user that also has the following privilege: [source, cypher] ---- @@ -100,7 +100,7 @@ When calling the user-defined function `MATCH (a:A) RETURN apoc.any.properties(a ==== A user-defined function may also be executed with elevated privileges using the -link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/dbms-administration#access-control-execute-boosted-user-defined-function[`EXECUTE BOOSTED USER DEFINED FUNCTION` privilege]. +xref:authentication-authorization/dbms-administration.adoc#access-control-execute-boosted-user-defined-function[`EXECUTE BOOSTED USER DEFINED FUNCTION` privilege]. [NOTE] -- @@ -119,7 +119,7 @@ GRANT EXECUTE BOOSTED USER DEFINED FUNCTION apoc.any.properties ON DBMS TO custo ---- This will allow any user with the `custom` role to execute the `apoc.any.properties` with elevated privileges. -E.g. a user that also have the following privileges: +E.g. a user that also has the following privileges: [source, cypher] ---- diff --git a/modules/ROOT/pages/authentication-authorization/manage-privileges.adoc b/modules/ROOT/pages/authentication-authorization/manage-privileges.adoc new file mode 100644 index 000000000..9043098a9 --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/manage-privileges.adoc @@ -0,0 +1,1646 @@ +:description: This section explains how to use Cypher to manage privileges for Neo4j role-based access control and fine-grained security. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated +[[access-control-manage-privileges]] + += Role-based access control + +Role-based access control (_RBAC_) is a method of restricting access to authorized users, by assigning users to specific roles with a particular set of privileges granted to them. +Privileges control the access rights to graph elements using a combined allowlist/denylist mechanism. +It is possible to grant or deny access, or use a combination of the two. +The user will be able to access the resource if they have a `GRANT` (allowlist) and do not have a `DENY` (denylist) relevant to that resource. +All other combinations of `GRANT` and `DENY` will result in the matching path being inaccessible. +What this means in practice depends on whether we are talking about a xref:authentication-authorization/privileges-reads.adoc[read privilege] or a xref:authentication-authorization/privileges-writes.adoc[write privilege]: + +* If an entity is not accessible due to xref:authentication-authorization/privileges-reads.adoc[read privileges], the data will become invisible. +It will appear to the user as if they had a smaller database (smaller graph). +* If an entity is not accessible due to xref:authentication-authorization/privileges-writes.adoc[write privileges], an error will occur on any attempt to write that data. + +[NOTE] +==== +In this document we will often use the terms _'allows'_ and _'enables'_ in seemingly identical ways. However, there is a subtle difference. +We will use _'enables'_ to refer to the consequences of xref:authentication-authorization/privileges-reads.adoc[read privileges] where a restriction will not cause an error, only a reduction in the apparent graph size. +We will use _'allows'_ to refer to the consequence of xref:authentication-authorization/privileges-writes.adoc[write privileges] where a restriction can result in an error. +==== + +[NOTE] +==== +If a user was not also provided with the database `ACCESS` privilege, then access to the entire database will be denied. +Information about the database access privilege can be found in xref:authentication-authorization/database-administration.adoc#access-control-database-administration-access[The ACCESS privilege]. +==== + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +[[access-control-graph-privileges]] +== Graph privilege commands + +Administrators can use the Cypher commands `GRANT`, `DENY`, and `REVOKE` to manage Neo4j graph administrative rights. +These commands can be used to grant or deny privileges to roles, and to revoke previously granted or denied privileges. +The privileges can be granted or denied on the entire graph or specific elements within the graph. +The privileges can also be made immutable, which means they cannot be granted, denied, or revoked unless auth is disabled. + +[[components-of-the-graph-privilege-commands]] +=== Components of the graph privilege commands + +The components of the graph privilege commands are: + +* _the command_: +** `GRANT` – gives privileges to roles. +** `DENY` – denies privileges to roles. +** `REVOKE` – removes granted or denied privileges from roles. + +* _mutability_: +** `IMMUTABLE` can optionally be specified when performing a `GRANT` or `DENY` to indicate that the privilege cannot be subsequently removed unless auth is disabled. +Auth must also be disabled in order to `GRANT` or `DENY` an immutable privilege. +Contrastingly, when `IMMUTABLE` is specified in conjunction with a `REVOKE` command, it will act as a filter and only remove matching _immutable_ privileges. +Starting from Neo4j 5.26, immutable privileges can also be used together with immutable roles. +See xref:authentication-authorization/immutable-roles-privileges.adoc[] for more information. + +* _graph-privilege_: +** Can be either a xref:authentication-authorization/privileges-reads.adoc[read privilege] or xref:authentication-authorization/privileges-writes.adoc[write privilege]. + +* _name_: +** The graph or graphs to associate the privilege with. +Because in Neo4j {neo4j-version} you can have only one graph per database, this command uses the database name or alias to refer to that graph. +When using an alias, the command will be executed on the resolved graph. ++ +[NOTE] +==== +If you delete a database and create a new one with the same name, the new one will _NOT_ have the privileges previously assigned to the deleted graph. +==== +** It can be `+*+`, which means all graphs. +Graphs created after this command execution will also be associated with these privileges. + +** `HOME GRAPH` refers to the graph associated with the home database for that user. +The default database will be used as home database if a user does not have one configured. +If the user's home database changes for any reason after privileges have been created, then these privileges will be associated with the graph attached to the new database. +This can be quite powerful as it allows permissions to be switched from one graph to another simply by changing a user's home database. + +* _entity_ +** The graph elements this privilege applies to: +*** `NODES` label (nodes with the specified label(s)). +*** `RELATIONSHIPS` type (relationships of the specific type(s)). +*** `ELEMENTS` label (both nodes and relationships). +*** `FOR` pattern (nodes that match the pattern). +See xref:authentication-authorization/property-based-access-control.adoc[Property-based access control] for details +** The label or type can be referred with `+*+`, which means all labels or types. +** Multiple labels or types can be specified, comma-separated. +** Defaults to `ELEMENTS` `+*+` if omitted. +** Some of the commands for write privileges do not allow an _entity_ part. +See xref:authentication-authorization/privileges-writes.adoc[Write privileges] for details. +** The `FOR` pattern _entity_ is not supported for write privileges. +* _role[, ...]_ +** The role or roles to associate the privilege with, comma-separated. + +[[general-syntax-for-graph-privilege-commands]] +=== General syntax for graph privilege commands + +.General grant +ON GRAPH+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +GRANT ... ON ... TO ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +GRANT [IMMUTABLE] graph-privilege ON { HOME GRAPH \| GRAPH[S] { * \| name[, ...] } } [entity] TO role[, ...] +---- + +| Description +a| Grants a privilege to one or multiple roles. + +|=== + +.General deny +ON GRAPH+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +DENY ... ON ... TO ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +DENY [IMMUTABLE] graph-privilege ON { HOME GRAPH \| GRAPH[S] { * \| name[, ...] } } [entity] TO role[, ...] +---- + +| Description +a| Denies a privilege to one or multiple roles. + +|=== + +.General revoke +ON GRAPH+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +REVOKE GRANT ... ON ... FROM ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +REVOKE [IMMUTABLE] GRANT graph-privilege ON { HOME GRAPH \| GRAPH[S] { * \| name[, ...] } } [entity] FROM role[, ...] +---- +| Description +a| Revokes a granted privilege from one or multiple roles. + +|=== + +.General revoke +ON GRAPH+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +REVOKE DENY ... ON ... FROM ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +REVOKE [IMMUTABLE] DENY graph-privilege ON { HOME GRAPH \| GRAPH[S] {* \| name[, ...] } } [entity] FROM role[, ...] +---- + +| Description +a| Revokes a denied privilege from one or multiple roles. + +|=== + +.General revoke +ON GRAPH+ privilege syntax +[cols="<15s,<85"] +|=== + +| Command +m| +REVOKE ... ON ... FROM ...+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +REVOKE [IMMUTABLE] graph-privilege ON { HOME GRAPH \| GRAPH[S] { * \| name[, ...] } } [entity] FROM role[, ...] +---- + +| Description +| Revokes a granted or denied privilege from one or multiple roles. +|=== + +[NOTE] +==== +`DENY` does NOT erase a granted privilege; they both exist. +Use `REVOKE` if you want to remove a privilege. +==== + +Common errors, such as misspellings or attempts to revoke privileges that have not been granted or denied, will result in notifications. +Some of these notifications may be replaced with errors in a future major version of Neo4j. +See link:{neo4j-docs-base-uri}/status-codes/{page-version}/notifications/all-notifications[Status Codes -> Notification codes] for details on notifications. + +The general `GRANT` and `DENY` syntaxes are illustrated in the following image: + +image::privileges_grant_and_deny_syntax.svg[width="800", title="GRANT and DENY Syntax"] + +A more detailed syntax illustration for graph privileges would be the following: + +image::privileges_on_graph_syntax.svg[width="800", title="Syntax of GRANT and DENY Graph Privileges. The `{` and `}` are part of the syntax and not used for grouping."] + +The following image shows the hierarchy between different graph privileges: + +image::privileges_hierarchy.svg[title="Graph privileges hierarchy"] + + +[role=label--new-5.9] +[[access-control-list-supported-privileges]] +== Listing supported privileges + +Supported privileges can be displayed using the `SHOW SUPPORTED PRIVILEGES` command. +This lists the privileges that are possible to grant or deny on a server, together with the structure of the privilege. + +.Show supported privileges command syntax +[cols="<15s,<85"] +|=== + +| Command +m| +SHOW SUPPORTED PRIVILEGES+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +SHOW SUPPORTED PRIVILEGE[S] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- +| Description +| List all privileges supported by the server. + +|=== + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +Results will include multiple columns describing the privileges: + +[options="header", width="100%", cols="4m,6a,2m"] +|=== +| Column | Description | Type + +| action +| The privilege action. +| STRING + +| qualifier +| Qualifier to further limit the target of the privilege (`function`, `label`, `procedure`, `property`, `setting`, `username`) or null if not applicable. +| STRING + +| target +| Target of the privilege: `dbms`, `database`, `graph`, `cidr`, or `all data`. +| STRING + +| scope +| List of possible scopes for the privilege (`elements`, `nodes`, `pattern`, `relationships`) or null if not applicable. +| LIST OF STRING + +| description +| A short description of the privilege. +| STRING + +|=== + +If a privilege lists a qualifier, it has to be used in the command by either an identifier or `*` if it should affect all identifiers. +The below table demonstrates how qualifiers are used: + +[options="header", width="100%", cols="2m,6m"] +|=== +| qualifier | example +| function | \... EXECUTE FUNCTION `abc*` ON ... +| label | \... SET LABEL `A` ON ... +| procedure | \... EXECUTE BOOSTED PROCEDURE `apoc.*` ON ... +| property | \... READ {`property`} ON ... +| setting | \... SHOW SETTINGS `dbms.*` ON ... +| username | \... IMPERSONATE (`username`) ON ... + +|=== + +It is optional to specify the scope of a privilege. +If it is not specified, the default scope will be `ELEMENT *`. +Note that not all privileges have a scope. + + +[[access-control-list-supported-privileges-example]] +=== Examples for listing supported privileges + +[source, cypher, role=noplay] +---- +SHOW SUPPORTED PRIVILEGES YIELD * ORDER BY action DESC LIMIT 10 RETURN action, qualifier, target, scope, description +---- + +Lists 10 supported privileges: + +.Result +[options="header,footer", width="100%", cols="m,m,m,m,m"] +|=== +|action +|qualifier +|target +|scope +|description + +| "write" +| NULL +| "graph" +| NULL +| "allows all WRITE operations on an entire graph" + +| "user management" +| NULL +| "dbms" +| NULL +| "enables the specified roles to create, delete, modify, and list users" + +| "traverse" +| NULL +| "graph" +| ["elements", "nodes", "pattern", "relationships"] +| "enables the specified entities to be found" + +| "transaction management" +| "username" +| "database" +| NULL +| "allows listing and ending transactions and queries for the specified users on the specified database" + +| "terminate transactions" +| "username" +| "database" +| NULL +| "allows ending transactions and queries for the specified users on the specified database" + +| "stop" +| NULL +| "database" +| NULL +| "allows the specified database to be stopped" + +| "start" +| NULL +| "database" +| NULL +| "allows the specified database to be started" + +| "show user" +| NULL +| "dbms" +| NULL +| "enables the specified roles to list users" + +| "show transactions" +| "username" +| "database" +| NULL +| "allows listing transactions and queries for the specified users on the specified database" + +| "show settings" +| "setting" +| "dbms" +| NULL +| "enables the specified roles to query given configuration settings" + +5+a|Rows: 10 +|=== + +[[access-control-list-privileges]] +== Listing assigned privileges + +Privileges that have been granted or denied to roles can be displayed using the following `SHOW PRIVILEGE[S]` commands. + +.Show privileges command syntax +[cols="<15s,<85"] +|=== + +| Command +m| +SHOW PRIVILEGE+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +SHOW [ALL] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- +| Description +| List all granted or denied privileges. + +|=== + +.Show role privileges syntax +[cols="<15s,<85"] +|=== + +| Command +m| +SHOW ROLE ... PRIVILEGE+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +SHOW ROLE[S] name[, ...] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +| List privileges granted or denied to a specific role. + +|=== + +.Show user privileges syntax +[cols="<15s,<85"] +|=== + +| Command +m| +SHOW USER ... PRIVILEGE+ + +| Syntax +a| +[source, syntax, role="noheader", indent=0] +---- +SHOW USER[S] [name[, ...]] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +| List privileges for a specific user, or the current user. + +[NOTE] +==== +Please note that it is only possible for a user to show their own privileges. +Therefore, if a non-native auth provider like LDAP is in use, `SHOW USER PRIVILEGES` will only work in a limited capacity. + +Other users' privileges cannot be listed when using a non-native auth provider. +==== +|=== + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +For an easy overview of the existing privileges, it is recommended to use the `AS COMMANDS` version of the `SHOW` command, which returns two columns. + +.`SHOW PRIVILEGES AS COMMANDS` output +[options="header", width="100%", cols="2a,4,2m"] +|=== +| Column +| Description +| Type + +| command +| The privilege as the command that is granted or denied. +Or in the `AS REVOKE COMMANDS` case, the command to revoke the privilege. label:default-output[] +| STRING + +| immutable +| Whether or not the privilege is immutable. +| BOOLEAN +|=== + +Alternatively, you can omit the `AS COMMANDS` clause and get the full details of the privileges returned in multiple columns. +They are all returned by default without requiring a `YIELD`. + +.`SHOW PRIVILEGES` output +[options="header", width="100%", cols="4m,6a,2m"] +|=== +| Column | Description | Type + +| access +| Whether the privilege is granted or denied. +| STRING + +| action +| The type of the privilege. +E.g., traverse, read, index management, or role management. +| STRING + +| resource +| The scope of the privilege. +E.g., the entire DBMS, a specific database, a graph, or sub-graph access. +| STRING + +| graph +| The specific database or graph the privilege applies to. +| STRING + +| segment +| The labels, relationship types, pattern, procedures, functions, transactions or settings the privilege applies to (if applicable). +| STRING + +| role +| The role the privilege is granted to. +| STRING + +| immutable +| Whether or not the privilege is immutable. +| BOOLEAN + +| user +| The user the privilege belongs to. + +Note that this is only returned for `SHOW USER [username] PRIVILEGES`. +| STRING + +|=== + +[[access-control-list-all-privileges]] +=== Examples for listing all privileges + +Assigned privileges can be displayed using the different `SHOW PRIVILEGE[S]` commands. + +[source, syntax] +---- +SHOW [ALL] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [WHERE expression] + +SHOW [ALL] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES +---- + +Lists all privileges for all roles: + +.Result +[options="header,footer", width="100%", cols="m,m,m,m,m,m,m"] +|=== +|access +|action +|resource +|graph +|segment +|role +|immutable + +|"GRANTED" +|"execute" +|"database" +|"*" +|"FUNCTION(*)" +|"PUBLIC" +|false + +|"GRANTED" +|"execute" +|"database" +|"*" +|"PROCEDURE(*)" +|"PUBLIC" +|false + +|"GRANTED" +|"access" +|"database" +|"DEFAULT" +|"database" +|"PUBLIC" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"NODE(*)" +|"admin" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"NODE(*)" +|"admin" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"RELATIONSHIP(*)" +|"admin" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"RELATIONSHIP(*)" +|"admin" +|false + +|"GRANTED" +|"transaction_management" +|"database" +|"*" +|"USER(*)" +|"admin" +|false + +|"GRANTED" +|"access" +|"database" +|"*" +|"database" +|"admin" +|false + +|"GRANTED" +|"constraint" +|"database" +|"*" +|"database" +|"admin" +|false + +|"GRANTED" +|"dbms_actions" +|"database" +|"*" +|"database" +|"admin" +|false + +|"GRANTED" +|"index" +|"database" +|"*" +|"database" +|"admin" +|false + +|"GRANTED" +|"start_database" +|"database" +|"*" +|"database" +|"admin" +|false + +|"GRANTED" +|"stop_database" +|"database" +|"*" +|"database" +|"admin" +|false + +|"GRANTED" +|"token" +|"database" +|"*" +|"database" +|"admin" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"NODE(*)" +|"architect" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"NODE(*)" +|"architect" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"RELATIONSHIP(*)" +|"architect" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"RELATIONSHIP(*)" +|"architect" +|false + +|"GRANTED" +|"access" +|"database" +|"*" +|"database" +|"architect" +|false + +|"GRANTED" +|"constraint" +|"database" +|"*" +|"database" +|"architect" +|false + +|"GRANTED" +|"index" +|"database" +|"*" +|"database" +|"architect" +|false + +|"GRANTED" +|"token" +|"database" +|"*" +|"database" +|"architect" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"NODE(*)" +|"editor" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"NODE(*)" +|"editor" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"RELATIONSHIP(*)" +|"editor" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"RELATIONSHIP(*)" +|"editor" +|false + +|"GRANTED" +|"access" +|"database" +|"*" +|"database" +|"editor" +|false + +|"DENIED" +|"access" +|"database" +|"neo4j" +|"database" +|"noAccessUsers" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"NODE(*)" +|"publisher" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"NODE(*)" +|"publisher" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"RELATIONSHIP(*)" +|"publisher" +|false + +|"GRANTED" +|"write" +|"graph" +|"*" +|"RELATIONSHIP(*)" +|"publisher" +|false + +|"GRANTED" +|"access" +|"database" +|"*" +|"database" +|"publisher" +|false + +|"GRANTED" +|"token" +|"database" +|"*" +|"database" +|"publisher" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"NODE(*)" +|"reader" +|false + +|"GRANTED" +|"match" +|"all_properties" +|"*" +|"RELATIONSHIP(*)" +|"reader" +|false + +|"GRANTED" +|"access" +|"database" +|"*" +|"database" +|"reader" +|false + +|"GRANTED" +|"access" +|"database" +|"neo4j" +|"database" +|"regularUsers" +|false + +7+a|Rows: 39 +|=== + + +[NOTE] +==== +The `token` action corresponds to the `NAME MANAGEMENT` privilege. +==== + +It is also possible to filter and sort the results by using `YIELD`, `ORDER BY` and `WHERE`: + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES YIELD role, access, action, segment +ORDER BY action +WHERE role = 'admin' +---- + +In this example: + +* The number of columns returned has been reduced with the `YIELD` clause. +* The order of the returned columns has been changed. +* The results have been filtered to only return the `admin` role using a `WHERE` clause. +* The results are ordered by the `action` column using `ORDER BY`. + +`SKIP` and `LIMIT` can also be used to paginate the results. + +.Result +[options="header,footer", width="100%", cols="m,m,m,m"] +|=== +|role +|access +|action +|segment + +|"admin" +|"GRANTED" +|"access" +|"database" + +|"admin" +|"GRANTED" +|"constraint" +|"database" + +|"admin" +|"GRANTED" +|"dbms_actions" +|"database" + +|"admin" +|"GRANTED" +|"index" +|"database" + +|"admin" +|"GRANTED" +|"match" +|"NODE(*)" + +|"admin" +|"GRANTED" +|"match" +|"RELATIONSHIP(*)" + +|"admin" +|"GRANTED" +|"start_database" +|"database" + +|"admin" +|"GRANTED" +|"stop_database" +|"database" + +|"admin" +|"GRANTED" +|"token" +|"database" + +|"admin" +|"GRANTED" +|"transaction_management" +|"USER(*)" + +|"admin" +|"GRANTED" +|"write" +|"NODE(*)" + +|"admin" +|"GRANTED" +|"write" +|"RELATIONSHIP(*)" + +4+a|Rows: 12 +|=== + +[NOTE] +==== +The `token` action corresponds to the `NAME MANAGEMENT` privilege. +==== + +`WHERE` can also be used without `YIELD`: + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES +WHERE graph <> '*' +---- + +In this example, the `WHERE` clause is used to filter privileges down to those that target specific graphs only. + +.Result +[options="header,footer", width="100%", cols="m,m,m,m,m,m"] +|=== +|access +|action +|graph +|resource +|role +|segment + +|"GRANTED" +|"access" +|"DEFAULT" +|"database" +|"PUBLIC" +|"database" + +|"DENIED" +|"access" +|"neo4j" +|"database" +|"noAccessUsers" +|"database" + +|"GRANTED" +|"access" +|"neo4j" +|"database" +|"regularUsers" +|"database" + +6+a|Rows: 3 +|=== + +Aggregations in the `RETURN` clause can be used to group privileges. +In this case, by user and `GRANTED` or `DENIED`: + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES YIELD * RETURN role, access, collect([graph, resource, segment, action]) AS privileges +---- + +.Result +[options="header,footer", width="100%", cols="1m,1m,3m"] +|=== +|role +|access +|privileges + +|"PUBLIC" +|"GRANTED" +|[["\*","database","FUNCTION(*)","execute"],["\*","database","PROCEDURE(*)","execute"],["DEFAULT","database","database","access"]] + +|"admin" +|"GRANTED" +|[["\*","all_properties","NODE(*)","match"],["\*","graph","NODE(*)","write"],["\*","all_properties","RELATIONSHIP(*)","match"],["\*","graph","RELATIONSHIP(*)","write"],["\*","database","USER(*)","transaction_management"],["\*","database","database","access"],["*","database","database","constraint"],["\*","database","database","dbms_actions"],["*","database","database","index"],["\*","database","database","start_database"],["*","database","database","stop_database"],["*","database","database","token"]] + +|"architect" +|"GRANTED" +|[["\*","all_properties","NODE(*)","match"],["\*","graph","NODE(*)","write"],["\*","all_properties","RELATIONSHIP(*)","match"],["\*","graph","RELATIONSHIP(*)","write"],["\*","database","database","access"],["*","database","database","constraint"],["\*","database","database","index"],["*","database","database","token"]] + +|"editor" +|"GRANTED" +|[["\*","all_properties","NODE(*)","match"],["\*","graph","NODE(*)","write"],["\*","all_properties","RELATIONSHIP(*)","match"],["\*","graph","RELATIONSHIP(*)","write"],["*","database","database","access"]] + +|"noAccessUsers" +|"DENIED" +|[["neo4j","database","database","access"]] + +|"publisher" +|"GRANTED" +|[["\*","all_properties","NODE(*)","match"],["\*","graph","NODE(*)","write"],["\*","all_properties","RELATIONSHIP(*)","match"],["\*","graph","RELATIONSHIP(*)","write"],["\*","database","database","access"],["*","database","database","token"]] + +|"reader" +|"GRANTED" +|[["\*","all_properties","NODE(*)","match"],["\*","all_properties","RELATIONSHIP(*)","match"],["*","database","database","access"]] + +|"regularUsers" +|"GRANTED" +|[["neo4j","database","database","access"]] + +3+a|Rows: 8 +|=== + +[NOTE] +==== +The `token` action corresponds to the `NAME MANAGEMENT` privilege. +==== + +The `RETURN` clause can also be used to order and paginate the results, which is useful when combined with `YIELD` and `WHERE`. +In this example the query returns privileges for display five-per-page, and skips the first five to display the second page. + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES YIELD * RETURN * ORDER BY role SKIP 5 LIMIT 5 +---- + +.Result +[options="header,footer", width="100%", cols="2m,2m,1m,2m,1m,2m,1m"] +|=== +|access +|action +|graph +|resource +|role +|segment +|immutable + +|"GRANTED" +|"match" +|"*" +|"all_properties" +|"admin" +|"RELATIONSHIP(*)" +|false + +|"GRANTED" +|"write" +|"*" +|"graph" +|"admin" +|"RELATIONSHIP(*)" +|false + +|"GRANTED" +|"transaction_management" +|"*" +|"database" +|"admin" +|"USER(*)" +|false + +|"GRANTED" +|"access" +|"*" +|"database" +|"admin" +|"database" +|false + +|"GRANTED" +|"constraint" +|"*" +|"database" +|"admin" +|"database" +|false + +7+a|Rows: 5 +|=== + +Available privileges can also be displayed as Cypher commands by adding `AS COMMAND[S]`: + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"DENY ACCESS ON DATABASE `neo4j` TO `noAccessUsers`" +|"GRANT ACCESS ON DATABASE * TO `admin`" +|"GRANT ACCESS ON DATABASE * TO `architect`" +|"GRANT ACCESS ON DATABASE * TO `editor`" +|"GRANT ACCESS ON DATABASE * TO `publisher`" +|"GRANT ACCESS ON DATABASE * TO `reader`" +|"GRANT ACCESS ON DATABASE `neo4j` TO `regularUsers`" +|"GRANT ACCESS ON HOME DATABASE TO `PUBLIC`" +|"GRANT ALL DBMS PRIVILEGES ON DBMS TO `admin`" +|"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT EXECUTE FUNCTION * ON DBMS TO `PUBLIC`" +|"GRANT EXECUTE PROCEDURE * ON DBMS TO `PUBLIC`" +|"GRANT INDEX MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT INDEX MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `admin`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `architect`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `editor`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `publisher`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `reader`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `admin`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `architect`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `editor`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `publisher`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `reader`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `publisher`" +|"GRANT START ON DATABASE * TO `admin`" +|"GRANT STOP ON DATABASE * TO `admin`" +|"GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * TO `admin`" +|"GRANT WRITE ON GRAPH * TO `admin`" +|"GRANT WRITE ON GRAPH * TO `architect`" +|"GRANT WRITE ON GRAPH * TO `editor`" +|"GRANT WRITE ON GRAPH * TO `publisher`" +a|Rows: 35 +|=== + +Like other `SHOW` commands, the output can also be processed using `YIELD` / `WHERE` / `RETURN`: + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES AS COMMANDS +WHERE command CONTAINS 'MANAGEMENT' +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT INDEX MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT INDEX MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `architect`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `publisher`" +|"GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * TO `admin`" +a|Rows: 8 +|=== + +It is also possible to get the privileges listed as revoking commands instead of granting or denying: + +[source, cypher, role=noplay] +---- +SHOW PRIVILEGES AS REVOKE COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"REVOKE DENY ACCESS ON DATABASE `neo4j` FROM `noAccessUsers`" +|"REVOKE GRANT ACCESS ON DATABASE * FROM `admin`" +|"REVOKE GRANT ACCESS ON DATABASE * FROM `architect`" +|"REVOKE GRANT ACCESS ON DATABASE * FROM `editor`" +|"REVOKE GRANT ACCESS ON DATABASE * FROM `publisher`" +|"REVOKE GRANT ACCESS ON DATABASE * FROM `reader`" +|"REVOKE GRANT ACCESS ON DATABASE `neo4j` FROM `regularUsers`" +|"REVOKE GRANT ACCESS ON HOME DATABASE FROM `PUBLIC`" +|"REVOKE GRANT ALL DBMS PRIVILEGES ON DBMS FROM `admin`" +|"REVOKE GRANT CONSTRAINT MANAGEMENT ON DATABASE * FROM `admin`" +|"REVOKE GRANT CONSTRAINT MANAGEMENT ON DATABASE * FROM `architect`" +|"REVOKE GRANT EXECUTE FUNCTION * ON DBMS FROM `PUBLIC`" +|"REVOKE GRANT EXECUTE PROCEDURE * ON DBMS FROM `PUBLIC`" +|"REVOKE GRANT INDEX MANAGEMENT ON DATABASE * FROM `admin`" +|"REVOKE GRANT INDEX MANAGEMENT ON DATABASE * FROM `architect`" +|"REVOKE GRANT MATCH {*} ON GRAPH * NODE * FROM `admin`" +|"REVOKE GRANT MATCH {*} ON GRAPH * NODE * FROM `architect`" +|"REVOKE GRANT MATCH {*} ON GRAPH * NODE * FROM `editor`" +|"REVOKE GRANT MATCH {*} ON GRAPH * NODE * FROM `publisher`" +|"REVOKE GRANT MATCH {*} ON GRAPH * NODE * FROM `reader`" +|"REVOKE GRANT MATCH {*} ON GRAPH * RELATIONSHIP * FROM `admin`" +|"REVOKE GRANT MATCH {*} ON GRAPH * RELATIONSHIP * FROM `architect`" +|"REVOKE GRANT MATCH {*} ON GRAPH * RELATIONSHIP * FROM `editor`" +|"REVOKE GRANT MATCH {*} ON GRAPH * RELATIONSHIP * FROM `publisher`" +|"REVOKE GRANT MATCH {*} ON GRAPH * RELATIONSHIP * FROM `reader`" +|"REVOKE GRANT NAME MANAGEMENT ON DATABASE * FROM `admin`" +|"REVOKE GRANT NAME MANAGEMENT ON DATABASE * FROM `architect`" +|"REVOKE GRANT NAME MANAGEMENT ON DATABASE * FROM `publisher`" +|"REVOKE GRANT START ON DATABASE * FROM `admin`" +|"REVOKE GRANT STOP ON DATABASE * FROM `admin`" +|"REVOKE GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * FROM `admin`" +|"REVOKE GRANT WRITE ON GRAPH * FROM `admin`" +|"REVOKE GRANT WRITE ON GRAPH * FROM `architect`" +|"REVOKE GRANT WRITE ON GRAPH * FROM `editor`" +|"REVOKE GRANT WRITE ON GRAPH * FROM `publisher`" +a|Rows: 35 +|=== + +For more info about revoking privileges, please see xref:authentication-authorization/manage-privileges.adoc#access-control-revoke-privileges[The REVOKE command]. + +[[access-control-list-privileges-role]] +=== Examples for listing privileges for specific roles + +Available privileges for specific roles can be displayed using `SHOW ROLE name PRIVILEGE[S]`: + +[source, syntax] +---- +SHOW ROLE[S] name[, ...] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [WHERE expression] + +SHOW ROLE[S] name[, ...] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +[source, cypher, role=noplay] +---- +SHOW ROLE regularUsers PRIVILEGES +---- + +Lists all privileges for role `regularUsers`. + +.Result +[options="header,footer", width="100%", cols="m,m,m,m,m,m,m"] +|=== +|access +|action +|graph +|resource +|role +|segment +|immutable + +|"GRANTED" +|"access" +|"database" +|"neo4j" +|"database" +|"regularUsers" +|false + +7+a|Rows: 1 +|=== + +[source, cypher, role=noplay] +---- +SHOW ROLES regularUsers, noAccessUsers PRIVILEGES +---- + +Lists all privileges for roles `regularUsers` and `noAccessUsers`. + +.Result +[options="header,footer", width="100%", cols="m,m,m,m,m,m,m"] +|=== +|access +|action +|graph +|resource +|role +|segment +|immutable + +|"DENIED" +|"access" +|"database" +|"neo4j" +|"database" +|"noAccessUsers" +|false + +|"GRANTED" +|"access" +|"database" +|"neo4j" +|"database" +|"regularUsers" +|false + +7+a|Rows: 2 +|=== + +Similar to the other `SHOW PRIVILEGES` commands, the available privileges for roles can also be listed as Cypher commands with the optional `AS COMMAND[S]`. + +[source, cypher, role=noplay] +---- +SHOW ROLES regularUsers, noAccessUsers PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON DATABASE * TO `admin`" +|"GRANT ALL DBMS PRIVILEGES ON DBMS TO `admin`" +|"GRANT CONSTRAINT MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT INDEX MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT MATCH {*} ON GRAPH * NODE * TO `admin`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `admin`" +|"GRANT NAME MANAGEMENT ON DATABASE * TO `admin`" +|"GRANT START ON DATABASE * TO `admin`" +|"GRANT STOP ON DATABASE * TO `admin`" +|"GRANT TRANSACTION MANAGEMENT (*) ON DATABASE * TO `admin`" +|"GRANT WRITE ON GRAPH * TO `admin`" +a|Rows: 11 +|=== + +The output can be processed using `YIELD` / `WHERE` / `RETURN` here as well: + +[source, cypher, role=noplay] +---- +SHOW ROLE architect PRIVILEGES AS COMMANDS WHERE command CONTAINS 'MATCH' +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT MATCH {*} ON GRAPH * NODE * TO `architect`" +|"GRANT MATCH {*} ON GRAPH * RELATIONSHIP * TO `architect`" +|Rows: 2 +|=== + +Again, it is possible to get the privileges listed as revoking commands instead of granting or denying. +For more info about revoking privileges, please see xref:authentication-authorization/manage-privileges.adoc#access-control-revoke-privileges[The REVOKE command]. + +[source, cypher, role=noplay] +---- +SHOW ROLE reader PRIVILEGES AS REVOKE COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"REVOKE GRANT ACCESS ON DATABASE * FROM `reader`" +|"REVOKE GRANT MATCH {*} ON GRAPH * NODE * FROM `reader`" +|"REVOKE GRANT MATCH {*} ON GRAPH * RELATIONSHIP * FROM `reader`" +a|Rows: 3 +|=== + +[[access-control-list-privileges-user]] +=== Examples for listing privileges for specific users + +Available privileges for specific users can be displayed using `SHOW USER name PRIVILEGES`. + +[NOTE] +==== +Note that if a non-native auth provider like LDAP is in use, `SHOW USER PRIVILEGES` will only work with a limited capacity as it is only possible for a user to show their own privileges. +Other users' privileges cannot be listed when using a non-native auth provider. +==== + +[source, syntax] +---- +SHOW USER[S] [name[, ...]] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [WHERE expression] + +SHOW USER[S] [name[, ...]] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +[source, cypher, role=noplay] +---- +SHOW USER jake PRIVILEGES +---- + +Lists all privileges for user `jake`. + +.Result +[options="header,footer", width="100%", cols="m,m,m,m,m,m,m,m"] +|=== +|access +|action +|resource +|graph +|resource +|role +|segment +|immutable + +|"GRANTED" +|"execute" +|"database" +|"*" +|"FUNCTION(*)" +|"PUBLIC" +|"jake" +|false + +|"GRANTED" +|"execute" +|"database" +|"*" +|"PROCEDURE(*)" +|"PUBLIC" +|"jake" +|false + +|"GRANTED" +|"access" +|"database" +|"DEFAULT" +|"database" +|"PUBLIC" +|"jake" +|false + +|"GRANTED" +|"access" +|"database" +|"neo4j" +|"database" +|"regularUsers" +|"jake" +|false + +8+a|Rows: 4 +|=== + +[source, cypher, role=noplay] +---- +SHOW USERS jake, joe PRIVILEGES +---- + +Lists all privileges for users `jake` and `joe`. + +.Result +[options="header,footer", width="100%", cols="m,m,m,m,m,m,m,m"] +|=== +|access +|action +|resource +|graph +|resource +|role +|segment +|immutable + +|"GRANTED" +|"execute" +|"database" +|"*" +|"FUNCTION(*)" +|"PUBLIC" +|"jake" +|false + +|"GRANTED" +|"execute" +|"database" +|"*" +|"PROCEDURE(*)" +|"PUBLIC" +|"jake" +|false + +|"GRANTED" +|"access" +|"database" +|"DEFAULT" +|"database" +|"PUBLIC" +|"jake" +|false + +|"GRANTED" +|"access" +|"database" +|"neo4j" +|"database" +|"regularUsers" +|"jake" +|false + +|"GRANTED" +|"execute" +|"database" +|"*" +|"FUNCTION(*)" +|"PUBLIC" +|"joe" +|false + +|"GRANTED" +|"execute" +|"database" +|"*" +|"PROCEDURE(*)" +|"PUBLIC" +|"joe" +|false + +|"GRANTED" +|"access" +|"database" +|"DEFAULT" +|"database" +|"PUBLIC" +|"joe" +|false + +|"DENIED" +|"access" +|"database" +|"neo4j" +|"database" +|"noAccessUsers" +|"joe" +|false + +8+a|Rows: 8 +|=== + +The same command can be used at all times to review available privileges for the current user. +For this purpose, there is a shorter form of the command: `SHOW USER PRIVILEGES`: + +[source, cypher, role=noplay] +---- +SHOW USER PRIVILEGES +---- + +As for the other privilege commands, available privileges for users can also be listed as Cypher commands with the optional `AS COMMAND[S]`. + +[NOTE] +==== +When showing user privileges as commands, the roles in the Cypher commands are replaced with a parameter. +This can be used to quickly create new roles based on the privileges of specific users. +==== + +[source, cypher, role=noplay] +---- +SHOW USER jake PRIVILEGES AS COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"GRANT ACCESS ON DATABASE `neo4j` TO $role" +|"GRANT ACCESS ON HOME DATABASE TO $role" +|"GRANT EXECUTE FUNCTION * ON DBMS TO $role" +|"GRANT EXECUTE PROCEDURE * ON DBMS TO $role" +a|Rows: 4 +|=== + +Like other `SHOW` commands, the output can also be processed using `YIELD` / `WHERE` / `RETURN`. +Additionally, similar to the other show privilege commands, it is also possible to show the commands for revoking the privileges. + +[source, cypher, role=noplay] +---- +SHOW USER jake PRIVILEGES AS REVOKE COMMANDS +WHERE command CONTAINS 'EXECUTE' +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"REVOKE GRANT EXECUTE FUNCTION * ON DBMS FROM $role" +|"REVOKE GRANT EXECUTE PROCEDURE * ON DBMS FROM $role" +a|Rows: 2 +|=== + +[[access-control-revoke-privileges]] +== Revoking privileges + +Privileges that were granted or denied earlier can be revoked using the `REVOKE` command: + +[source, syntax] +---- +REVOKE + [ IMMUTABLE ] + [ GRANT | DENY ] graph-privilege + FROM role[, ...] +---- + +An example usage of the `REVOKE` command is given here: + +[source, cypher, role=noplay] +---- +REVOKE GRANT TRAVERSE ON HOME GRAPH NODES Post FROM regularUsers +---- + +While it can be explicitly specified that `REVOKE` should remove a `GRANT` or `DENY`, it is also possible to `REVOKE` both by not specifying them at all, as the next example demonstrates. +Because of this, if there happens to be a `GRANT` and a `DENY` for the same privilege, it would remove both. + +[source, cypher, role=noplay] +---- +REVOKE TRAVERSE ON HOME GRAPH NODES Payments FROM regularUsers +---- + +Adding `IMMUTABLE` explicitly specifies that only immutable privileges should be removed. Omitting it specifies that both immutable and regular privileges should be removed. diff --git a/modules/ROOT/pages/authentication-authorization/manage-roles.adoc b/modules/ROOT/pages/authentication-authorization/manage-roles.adoc new file mode 100644 index 000000000..2d0226f04 --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/manage-roles.adoc @@ -0,0 +1,860 @@ +:description: This section explains how to use Cypher to manage roles in Neo4j. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated + +[[access-control-manage-roles]] += Manage roles + +//// +[source, cypher, role=test-setup] +---- +CREATE USER bob SET PASSWORD 'abcd1234' CHANGE NOT REQUIRED; +CREATE USER user1 SET PASSWORD 'abcd1234' CHANGE NOT REQUIRED; +CREATE USER user2 SET PASSWORD 'abcd1234' CHANGE NOT REQUIRED; +CREATE USER user3 SET PASSWORD 'abcd1234' CHANGE NOT REQUIRED; +CREATE ROLE myrole IF NOT EXISTS; +CREATE ROLE role1 IF NOT EXISTS; +CREATE ROLE role2 IF NOT EXISTS; +---- +//// + +Roles can be created and managed using a set of Cypher administration commands executed against the `system` database. + +When connected to the DBMS over `bolt`, administration commands are automatically routed to the `system` database. + + +[[access-control-role-syntax]] +== Role management command syntax + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +[cols="<15s,<85"] +|=== + +| Command +m| SHOW ROLES + +| Syntax +a| +[source, syntax, role="noheader"] +---- +SHOW [ALL\|POPULATED] ROLE[S] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +a| +Lists roles. + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-list-roles[Listing roles]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT SHOW ROLE +---- + + +See xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| SHOW ROLES WITH USERS + +| Syntax +a| +[source, syntax, role="noheader"] +---- +SHOW [ALL\|POPULATED] ROLE[S] WITH USER[S] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +a| +Lists roles and users assigned to them. + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-list-roles[Listing roles]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT SHOW ROLE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. + +[source, privilege, role="noheader"] +---- +GRANT SHOW USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| SHOW ROLE PRIVILEGES + +| Syntax +a| +[source, syntax, role="noheader"] +---- +SHOW ROLE[S] name[, ...] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +a| +Lists the privileges granted to the specified roles. + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +The `SHOW ROLE name PRIVILEGES` command is described in xref:authentication-authorization/manage-privileges.adoc#access-control-list-privileges[Listing privileges]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT SHOW PRIVILEGE +---- + +See xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-privilege-management[DBMS PRIVILEGE MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== + + +| Command +m| CREATE [IMMUTABLE] ROLE + +| Syntax +a| +[source, syntax, role="noheader"] +---- +CREATE ROLE name [IF NOT EXISTS] [AS COPY OF otherName] +---- + +| Description +a| +Creates a new role. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-create-roles[Creating roles]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT CREATE ROLE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. + +|=== + +[cols="<15s,<85"] +|=== +| Command +m| CREATE OR REPLACE ROLE + +| Syntax +a| +[source, syntax, role="noheader"] +---- +CREATE OR REPLACE ROLE name [AS COPY OF otherName] +---- + +| Description +a| +Creates a new role, or if a role with the same name exists, replace it. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-create-roles[Creating roles]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT CREATE ROLE +---- + +[source, privilege, role="noheader"] +---- +GRANT DROP ROLE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| RENAME ROLE + +| Syntax +a| +[source, syntax, role="noheader"] +---- +RENAME ROLE name [IF EXISTS] TO otherName +---- + +| Description +a| +Changes the name of a role. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-rename-roles[Renaming roles]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT RENAME ROLE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| DROP ROLE + +| Syntax +a| +[source, syntax, role="noheader"] +---- +DROP ROLE name [IF EXISTS] +---- + +| Description +a| +Removes a role. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-drop-roles[Deleting roles]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT DROP ROLE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| GRANT ROLE TO + +| Syntax +a| +[source, syntax, role="noheader"] +---- +GRANT ROLE[S] name[, ...] TO user[, ...] +---- + +| Description +a| +Assigns roles to users. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-assign-roles[Assigning roles to users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT ASSIGN ROLE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| REVOKE ROLE + +| Syntax +a| +[source, syntax, role="noheader"] +---- +REVOKE ROLE[S] name[, ...] FROM user[, ...] +---- + +| Description +a| +Removes roles from users. + +For more information, see xref:authentication-authorization/manage-roles.adoc#access-control-revoke-roles[Revoking roles from users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT REMOVE ROLE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[DBMS ROLE MANAGEMENT privileges]. + +|=== + + +[[access-control-list-roles]] +== Listing roles + + +You can view all available roles using the Cypher command `SHOW ROLES`, which returns a single column by default. +Starting from 5.26, you can optionally use `SHOW ROLES YIELD *` to see if the role is immutable. +See <> for more information. + +.`SHOW ROLES` output +[options="header", width="100%", cols="2a,4,2m"] +|=== +| Column +| Description +| Type + +| role +| Role name +| STRING + +| immutable +| `true` if the role is immutable, otherwise `false`. +| BOOLEAN +|=== + +.List all roles +==== +[source, cypher, role=noplay] +---- +SHOW ROLES +---- + +This is the same command as `SHOW ALL ROLES`. + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|role + +|"PUBLIC" +|"admin" +|"architect" +|"editor" +|"publisher" +|"reader" + +1+a|Rows: 6 +|=== +==== + +When first starting a Neo4j DBMS, there are a number of built-in roles: + +* `PUBLIC` - a role that all users have granted. +By default it gives access to the home database and to execute privileges for procedures and functions. +* `reader` - can perform traverse and read operations in all databases except `system`. +* `editor` - can perform traverse, read, and write operations in all databases except `system`, but cannot create new labels or relationship types. +* `publisher` - can do the same as `editor`, but also create new labels and relationship types. +* `architect` - can do the same as `publisher` as well as create and manage indexes and constraints. +* `admin` - can do the same as all the above, as well as manage databases, aliases, users, roles, and privileges. + +More information about the built-in roles and their privileges can be found in xref:authentication-authorization/built-in-roles.adoc[]. + +There are multiple versions of this command, the default being `SHOW ALL ROLES`. +To only show roles that are assigned to users, the command is `SHOW POPULATED ROLES`. +To see which users are assigned to which roles, `WITH USERS` can be added to the command. +The command produces a row per role per user and yields the following column in addition to the one output by `SHOW ROLES`: + +.`SHOW POPULATED ROLES WITH USERS` output +[options="header", width="100%", cols="2a,4,2m"] +|=== +| Column +| Description +| Type + +| member +| User name +| STRING +|=== + +Since this gives a result with one row for each user, it shows up twice if a role is assigned to two users. + +.Show roles with users +==== +[source, cypher, role=noplay] +---- +SHOW POPULATED ROLES WITH USERS +---- + +The table of results will show information about the role and what database it belongs to: + +.Result +[options="header,footer", width="100%", cols="m,m"] +|=== +|role +|member + +|"PUBLIC" +|"neo4j" + +|"PUBLIC" +|"bob" + +|"PUBLIC" +|"user1" + +|"PUBLIC" +|"user2" + +|"PUBLIC" +|"user3" + +|"admin" +|"neo4j" + +2+a|Rows: 6 +|=== +==== + +It is also possible to filter and sort the results by using `YIELD`, `ORDER BY` and `WHERE`. + +.Show roles with ordering and filtering +==== +[source, cypher, role=noplay] +---- +SHOW ROLES YIELD role +ORDER BY role +WHERE role ENDS WITH 'r' +---- + +In this example: + +* The results have been filtered to only return the roles ending in 'r'. +* The results are ordered by the `action` column using `ORDER BY`. + +It is also possible to use `SKIP` and `LIMIT` to paginate the results. + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|role + +|"editor" +|"publisher" +|"reader" + +1+a|Rows: 3 +|=== +==== + + +[[access-control-create-roles]] +== Creating roles + +Roles can be created using `CREATE [IMMUTABLE] ROLE`: + +[source, syntax] +---- +CREATE [IMMUTABLE] ROLE name [IF NOT EXISTS] [AS COPY OF otherName] +---- + +Roles can be created or replaced by using `CREATE OR REPLACE [IMMUTABLE] ROLE`: + +[source, syntax] +---- +CREATE OR REPLACE [IMMUTABLE] ROLE name [AS COPY OF otherName] +---- + +[NOTE] +==== +The following naming rules apply: + +* The first character must be an ASCII alphabetic character. +* Subsequent characters can be ASCII alphabetic, numeric characters, and underscore. +* Role names are case sensitive. +==== + +A role can be copied, keeping its privileges, using `CREATE [IMMUTABLE] ROLE name AS COPY OF otherName`. + +.Copy a role +====== +[source, cypher, role=noplay] +---- +CREATE ROLE mysecondrole AS COPY OF myrole +---- +====== + +Created roles will appear on the list provided by `SHOW ROLES`. + +.List roles +====== +[source, cypher, role=noplay] +---- +SHOW ROLES +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|role + +|"PUBLIC" +|"admin" +|"architect" +|"editor" +|"myrole" +|"mysecondrole" +|"publisher" +|"reader" + +1+a|Rows: 8 +|=== +====== + +The `CREATE ROLE` command is optionally idempotent, with the default behavior to throw an exception if the role already exists. +Adding `IF NOT EXISTS` to the `CREATE ROLE` command will ensure that no exception is thrown and nothing happens should the role already exist. + +.Create role if not exists +====== + +[source, cypher, role=noplay] +---- +CREATE ROLE myrole IF NOT EXISTS +---- + +====== + + +The `CREATE OR REPLACE ROLE` command will result in any existing role being deleted and a new one created. + + +.Create or replace role +====== + +[source, cypher, role=noplay] +---- +CREATE OR REPLACE ROLE myrole +---- + +This is equivalent to running `DROP ROLE myrole IF EXISTS` followed by `CREATE ROLE myrole`. + +====== + + +[NOTE] +==== +The `CREATE OR REPLACE ROLE` command does not allow you to use the `IF NOT EXISTS`. +==== + +[role=new-in-5.26] +[[access-control-immutable-roles]] +== Immutable roles + +Immutable roles are those that cannot be modified in the usual way. +This means they cannot be created, renamed, dropped, or have privileges granted to or revoked from them under normal operating conditions. +See xref:authentication-authorization/immutable-roles-privileges.adoc[Immutable roles and privileges] for details of when and how the `IMMUTABLE` keyword may be used. + +They are useful in cases where you need a permanent built-in system role that cannot be modified even by users who have xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-role-management[`ROLE MANAGEMENT` privileges] but yet can be granted to and revoked from users in the same way as an ordinary role. + + +[[access-control-rename-roles]] +== Renaming roles + +Roles can be renamed using `RENAME ROLE` command: + +[source, cypher, role=noplay] +---- +RENAME ROLE mysecondrole TO mythirdrole +---- + +[source, cypher, role=noplay] +---- +SHOW ROLES +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|role + +|"PUBLIC" +|"admin" +|"architect" +|"editor" +|"myrole" +|"mythirdrole" +|"publisher" +|"reader" + +1+a|Rows: 8 +|=== + +[NOTE] +==== +The `RENAME ROLE` command is only available when using native authentication and authorization. +==== + + +[[access-control-assign-roles]] +== Assigning roles to users + +Users can be given access rights by assigning them roles using `GRANT ROLE`: + +[source, cypher, role=noplay] +---- +GRANT ROLE myrole TO bob +---- + +The roles assigned to each user can be seen on the list provided by xref:authentication-authorization/manage-users.adoc#access-control-list-users[`SHOW USERS`]: + +[source, cypher, role=noplay] +---- +SHOW USERS +---- + +.Result +[options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user +|roles +|passwordChangeRequired +|suspended +|home + +|"bob" +|["myrole","PUBLIC"] +|false +|false +| + +|"neo4j" +|["admin","PUBLIC"] +|true +|false +| + +|"user1" +|["PUBLIC"] +|true +|false +| + +|"user2" +|["PUBLIC"] +|true +|false +| + +|"user3" +|["PUBLIC"] +|true +|false +| + +5+a|Rows: 5 +|=== + +It is possible to assign multiple roles to multiple users in one command: + +[source, cypher, role=noplay] +---- +GRANT ROLES role1, role2 TO user1, user2, user3 +---- + +[source, cypher, role=noplay] +---- +SHOW USERS +---- + +.Result +[options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user +|roles +|passwordChangeRequired +|suspended +|home + +|"bob" +|["myrole","PUBLIC"] +|false +|false +| + +|"neo4j" +|["admin","PUBLIC"] +|true +|false +| + +|"user1" +|["role1","role2","PUBLIC"] +|true +|false +| + +|"user2" +|["role1","role2","PUBLIC"] +|true +|false +| + +|"user3" +|["role1","role2","PUBLIC"] +|true +|false +| + +5+a|Rows: 5 +|=== + +Common errors, such as attempts to grant roles to users who have already been granted those roles, will lead to notifications. +Some of these notifications may be replaced with errors in a future major version of Neo4j. +See link:{neo4j-docs-base-uri}/status-codes/{page-version}/notifications/all-notifications[Status Codes -> Notification codes] for details on notifications. + +[[access-control-revoke-roles]] +== Revoking roles from users + +Users can lose access rights by revoking their role using `REVOKE ROLE`: + +[source, cypher, role=noplay] +---- +REVOKE ROLE myrole FROM bob +---- + +The roles revoked from users can no longer be seen on the list provided by `SHOW USERS`: + +[source, cypher, role=noplay] +---- +SHOW USERS +---- + +.Result +[options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user +|roles +|passwordChangeRequired +|suspended +|home + +|"bob" +|["PUBLIC"] +|false +|false +| + +|"neo4j" +|["admin","PUBLIC"] +|true +|false +| + +|"user1" +|["role1","role2","PUBLIC"] +|true +|false +| + +|"user2" +|["role1","role2","PUBLIC"] +|true +|false +| + +|"user3" +|["role1","role2","PUBLIC"] +|true +|false +| + +5+a|Rows: 5 +|=== + +It is possible to revoke multiple roles from multiple users in one command: + +[source, cypher, role=noplay] +---- +REVOKE ROLES role1, role2 FROM user1, user2, user3 +---- + +Common errors, such as misspellings or attempts to revoke roles from users who have not been granted those roles, will lead to notifications. +Some of these notifications may be replaced with errors in a future major version of Neo4j. +See link:{neo4j-docs-base-uri}/status-codes/{page-version}/notifications/all-notifications[Status Codes -> Notification codes] for details on notifications. + +[[access-control-drop-roles]] +== Deleting roles + +Roles can be deleted using `DROP ROLE` command: + +[source, cypher, role=noplay] +---- +DROP ROLE mythirdrole +---- + +When a role has been deleted, it will no longer appear on the list provided by `SHOW ROLES`: + +[source, cypher, role=noplay] +---- +SHOW ROLES +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|role + +|"PUBLIC" +|"admin" +|"architect" +|"editor" +|"myrole" +|"publisher" +|"reader" + +1+a|Rows: 8 +|=== + +This command is optionally idempotent, with the default behavior to throw an exception if the role does not exist. +Adding `IF EXISTS` to the command will ensure that no exception is thrown and nothing happens should the role not exist: + +[source, cypher, role=noplay] +---- +DROP ROLE mythirdrole IF EXISTS +---- diff --git a/modules/ROOT/pages/authentication-authorization/manage-users.adoc b/modules/ROOT/pages/authentication-authorization/manage-users.adoc new file mode 100644 index 000000000..faf64d0d3 --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/manage-users.adoc @@ -0,0 +1,1237 @@ +:description: This section explains how to use Cypher to manage users in Neo4j. + +[[access-control-manage-users]] += Manage users + +Users can be created and managed using a set of Cypher administration commands executed against the `system` database. +When connected to the DBMS over `bolt`, administration commands are automatically routed to the `system` database. + +== User states + +There are two types of user states in the `system` database: + +`ACTIVE` state:: (default for new users) +Users can log into Neo4j and perform queries according to their privileges. + +// [role=label--enterprise-edition] +`SUSPENDED` state label:enterprise-edition[]:: + +* Native users who authenticate and authorize against the system graph cannot log into Neo4j. +If suspended while using Neo4j, they lose all assigned roles with their privileges, including the `PUBLIC` role, until reactivated. +* Users who authenticate and authorize against an external ID provider (e.g., LDAP) can still log in. +If suspended while using Neo4j, they retain the roles and the privileges assigned by the external provider, including the `PUBLIC` role. +To prevent any of these, you need to use the mechanisms of their identity provider. + +[[access-control-user-syntax]] +== User management command syntax + +[NOTE] +==== +For more details about the syntax descriptions, see xref:database-administration/syntax.adoc[]. +==== + +[cols="<15s,<85"] +|=== + +| Command +m| SHOW CURRENT USER + +| Syntax +a| +[source, syntax, role="noheader"] +---- +SHOW CURRENT USER + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +a| +Lists the current user. + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-current-users[Listing current user]. + +| Required privilege +a| None + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| SHOW USERS + +| Syntax +a| +[source, syntax, role="noheader"] +---- +SHOW USER[S] + [WITH AUTH] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +a| +Lists all users. + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-list-users[Listing users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT SHOW USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== +| Command +m| SHOW USER PRIVILEGES + +| Syntax +a| +[source, syntax, role="noheader"] +---- +SHOW USER[S] [name[, ...]] PRIVILEGE[S] [AS [REVOKE] COMMAND[S]] + [YIELD { * \| field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] + [WHERE expression] + [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] +---- + +| Description +a| +Lists the privileges granted to the specified users or the current user if no user is specified. + +When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. + +The `SHOW USER name PRIVILEGES` command is described in xref:authentication-authorization/manage-privileges.adoc#access-control-list-privileges[Listing privileges]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT SHOW PRIVILEGE +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-privilege-management[DBMS PRIVILEGE MANAGEMENT privileges]. + +[source, privilege, role="noheader"] +---- +GRANT SHOW USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. +|=== + + +[cols="<15s,<85"] +|=== +| Command +m| CREATE USER + +| Syntax +a| +[source, syntax, role="noheader"] +---- +CREATE USER name [IF NOT EXISTS] + [SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password'] + [[SET PASSWORD] CHANGE [NOT] REQUIRED] + [SET STATUS {ACTIVE \| SUSPENDED}] + [SET HOME DATABASE name] + [SET AUTH [PROVIDER] 'provider' "{"{SET }..."}"]... # Introduced in Neo4j 5.24 +---- + +`` pairs for the `SET AUTH` clause could include: +[source, syntax, role="noheader"] +---- +SET AUTH [PROVIDER] 'provider' "{" + { + SET ID 'id' # a unique identifier of the user in an external system + \| SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password' # only applicable to the 'native' provider + \| SET PASSWORD CHANGE [NOT] REQUIRED # only applicable to the 'native' provider + } +"}" +---- + +| Description +a| +Creates a new user. + +[NOTE] +==== +It is mandatory to specify a `SET PASSWORD` and/or at least one `SET AUTH` clause because users must have at least one auth provider. +==== + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-create-users[Creating users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT CREATE USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + +|=== + +[cols="<15s,<85"] +|=== +| Command +m| CREATE OR REPLACE USER + +| Syntax +a| +[source, syntax, role="noheader"] +---- +CREATE OR REPLACE USER name + [SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password'] + [[SET PASSWORD] CHANGE [NOT] REQUIRED] + [SET STATUS {ACTIVE \| SUSPENDED}] + [SET HOME DATABASE name] + [SET AUTH [PROVIDER] 'provider' "{"{SET }..."}"]... # Introduced in Neo4j 5.24 +---- +`` pairs for the `SET AUTH` clause could include: +[source, syntax, role="noheader"] +---- +SET AUTH [PROVIDER] 'provider' "{" + { + SET ID 'id' # a unique identifier of the user in an external system + \| SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password' # only applicable to the 'native' provider + \| SET PASSWORD CHANGE [NOT] REQUIRED # only applicable to the 'native' provider + } +"}" +---- + +| Description +a| +Creates a new user, or if a user with the same name exists, replace it. + +[NOTE] +==== +It is mandatory to specify a `SET PASSWORD` and/or at least one `SET AUTH` clause because users must have at least one auth provider. +==== + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-create-users[Creating users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT CREATE USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + + +[source, privilege, role="noheader"] +---- +GRANT DROP USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + +|=== + +[cols="<15s,<85"] +|=== +| Command +m| RENAME USER + +| Syntax +a| +[source, syntax, role="noheader"] +---- +RENAME USER name [IF EXISTS] TO otherName +---- + +| Description +a| +Changes the name of a user. + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-rename-users[Renaming users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT RENAME USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + +|=== + +[cols="<15s,<85"] +|=== +| Command +m| ALTER USER + +| Syntax +a| +[source, syntax, role="noheader"] +---- +ALTER USER name [IF EXISTS] + [REMOVE HOME DATABASE] + [REMOVE { AUTH [PROVIDER[S]] provider[, ...] \| ALL AUTH [PROVIDER[S]] }]... + [SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password'] + [[SET PASSWORD] CHANGE [NOT] REQUIRED] + [SET STATUS {ACTIVE \| SUSPENDED} ] + [SET HOME DATABASE name] + [SET AUTH [PROVIDER] 'provider' "{"{SET }..."}"]... # Introduced in Neo4j 5.24 +---- +`` pairs for the `SET AUTH` clause could include: +[source, syntax, role="noheader"] +---- +SET AUTH [PROVIDER] 'provider' "{" + { + SET ID 'id' # a unique identifier of the user in an external system + \| SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password' # PASSWORD clauses are only applicable to the 'native' provider + \| SET PASSWORD CHANGE [NOT] REQUIRED # PASSWORD clauses are only applicable to the 'native' provider + } +"}" +---- + +| Description +a| +Modifies the settings for an existing user. + +* At least one `SET` or `REMOVE` clause is required. +* Any `REMOVE` clause(s) must appear before the first `SET` clause. + + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-alter-users[Modifying users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT SET PASSWORD +---- + +[source, privilege, role="noheader"] +---- +GRANT SET USER STATUS +---- + +[source, privilege, role="noheader"] +---- +GRANT SET USER HOME DATABASE +---- + +[source, privilege, role="noheader"] +---- +GRANT SET AUTH +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| ALTER CURRENT USER SET PASSWORD + +| Syntax +a| +[source, syntax, role="noheader"] +---- +ALTER CURRENT USER SET PASSWORD FROM 'oldPassword' TO 'newPassword' +---- + +| Description +a| +Changes the current user's password. + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-alter-password[Changing the current user's password]. + +| Required privilege +a| None + +|=== + + +[cols="<15s,<85"] +|=== + +| Command +m| DROP USER + +| Syntax +a| +[source, syntax, role="noheader"] +---- +DROP USER name [IF EXISTS] +---- + +| Description +a| +Removes an existing user. + +For more information, see xref:authentication-authorization/manage-users.adoc#access-control-drop-users[Delete users]. + +| Required privilege +a| +[source, privilege, role="noheader"] +---- +GRANT DROP USER +---- + +For more information, see xref:authentication-authorization/dbms-administration.adoc#access-control-dbms-administration-user-management[DBMS USER MANAGEMENT privileges]. + +|=== + + +[NOTE,role=label--enterprise-edition] +==== +The `SHOW USER[S] PRIVILEGES` command is described in xref:authentication-authorization/manage-privileges.adoc#access-control-list-privileges[Listing privileges]. +==== + + +[[access-control-current-users]] +== Listing current user + +You can view the currently logged-in user using the Cypher command `SHOW CURRENT USER`. +It produces a table with the following columns: + +[options="header", width="100%", cols="2a,4,2m,^.^,^.^"] +|=== +| Column +| Description +| Type +| Community Edition +| Enterprise Edition + +| user +| User name +| STRING +| {check-mark} +| {check-mark} + +| roles +| Roles granted to the user. + +It returns `null` in Community edition. +| LIST OF STRING +| {cross-mark} +| {check-mark} + +| passwordChangeRequired +| If `true`, the user must change their password at the next login. +This is `null` if the user has `native` auth disabled. +| BOOLEAN +| {check-mark} +| {check-mark} + +| suspended +| If `true`, the user is currently suspended. + +It returns `null` in Community edition. +| BOOLEAN +| {cross-mark} +| {check-mark} + +| home +| The home database configured by the user, or `null` if no home database has been configured. +If this database is unavailable and the user does not specify a database to use, they will not be able to log in. + +It returns `null` in Community edition. +| STRING +| {cross-mark} +| {check-mark} +|=== + +[source, cypher, role=noplay] +---- +SHOW CURRENT USER +---- + +.Result +[options="header,footer", width="100%", cols="2m,2m,3m,2m,2m"] +|=== +|user +|roles +|passwordChangeRequired +|suspended +|home + +|"jake" +|["PUBLIC"] +|false +|false +| + +5+a|Rows: 1 +|=== + +[NOTE] +==== +This command is only supported for a logged-in user and returns an empty result if authorization has been disabled. +==== + + +[[access-control-list-users]] +== Listing users + +You can list all available users using the Cypher command `SHOW USERS`. +It produces a table containing a single row per user with the following columns: + +[options="header", width="100%", cols="2a,4,2m,^.^,^.^"] +|=== +| Column +| Description +| Type +| Community Edition +| Enterprise Edition + +| user +| User name +| STRING +| {check-mark} +| {check-mark} + +| roles +| Native roles granted to the user using the `GRANT ROLE` command. + +The set of roles a user receives in practice may differ from those in this column. +It depends on DMBS configuration and the user's xref:authentication-authorization/auth-providers.adoc[auth providers]. + +For example, if they use external (e.g. LDAP or OIDC) auth, or if `native` is not listed in the xref:configuration/configuration-settings.adoc#config_dbms.security.authorization_providers[`dbms.security.authorization_providers`] configuration setting. + +It returns `null` in Community edition. +| LIST OF STRING +| {cross-mark} +| {check-mark} + +| passwordChangeRequired +| If `true`, the user must change their password at the next login. +This is `null` if the user has `native` auth disabled. +| BOOLEAN +| {check-mark} +| {check-mark} + +| suspended +| If `true`, the user is currently suspended. + +It returns `null` in Community edition. +| BOOLEAN +| {cross-mark} +| {check-mark} + +| home +| The home database configured for the user, otherwise `null`. +A home database is resolved if it is pointing to a database or a database alias. +If the configured home database is unavailable and the user does not specify another database, the login will fail. + +It returns `null` in Community edition. +| STRING +| {cross-mark} +| {check-mark} +|=== + +[NOTE] +==== +When first starting a Neo4j DBMS, there is always a single default user `neo4j` with administrative privileges. +It is possible to set the initial password using xref:configuration/set-initial-password.adoc[`neo4j-admin dbms set-initial-password `], otherwise you must change the password after the first login. +==== + +.Show users +====== +[source, cypher, role=noplay] +---- +SHOW USERS +---- + +.Result +[role="queryresult" options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user +|roles +|passwordChangeRequired +|suspended +|home + +|"neo4j" +|["admin","PUBLIC"] +|false +|false +| +|"jake" +|["PUBLIC"] +|false +|false +| +5+a|Rows: 2 +|=== +====== + +.Show user with column reorder and filtering +====== +This example shows how to: + +* Reorder the columns using a `YIELD` clause. +* Filter the results using a `WHERE` clause. + +[source, cypher, role=noplay] +---- +SHOW USER YIELD user, suspended, passwordChangeRequired, roles, home +WHERE user = 'jake' +---- + +.Result +[role="queryresult" options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user +|suspended +|passwordChangeRequired +|roles +|home +|"jake" +|false +|false +|["PUBLIC"] +| +5+a|Rows: 1 +|=== + +====== + +.Show user with `RETURN` clause +====== +It is possible to add a `RETURN` clause to further manipulate the results after filtering. +In this example, the `RETURN` clause is used to filter out the `roles` column and rename the `user` column to `adminUser`. + +[source,cypher,role=noplay] +---- +SHOW USERS YIELD roles, user +WHERE 'admin' IN roles +RETURN user AS adminUser +---- +.Result +[role="queryresult" options="header,footer", width="100%", cols="2m"] +|=== +|adminUser +|"neo4j" +1+a|Rows: 1 +|=== +====== + +[role=label--new-5.24] +[[access-control-list-user-auth-providers]] +== Listing user auth providers + +To inspect available user auth providers, use `SHOW USERS WITH AUTH`. +The command produces a row per user per auth provider and yields the following two columns in addition to those output by `SHOW USERS`: + +[options="header", width="100%", cols="1a,4,1m,^.^,^.^"] +|=== +| Column +| Description +| Type +| Community Edition +| Enterprise Edition + +| provider +| The name of the auth provider. +| STRING +| {check-mark} +| {check-mark} + +| auth +| A map containing configuration for the user. +For example, dn of the user for an `ldap` auth provider, the unique external identifier for an `oidc` auth provider, or password status for a `native` auth provider. + +| MAP +| {check-mark} +| {check-mark} +|=== + +.Show users with auth +====== +[source, cypher, role=noplay] +---- +SHOW USERS WITH AUTH +---- + +.Result +[role="queryresult" options="header,footer", width="100%", cols="2m,3m,3m,2m,2m,3m,4m"] +|=== +|user +|roles +|passwordChangeRequired +|suspended +|home +|provider +|auth +|"neo4j" +|["admin","PUBLIC"] +|false +|false +| +|"native" +|{ +"password": "*********", +"changeRequired": false +} +|"jack" +|["PUBLIC"] +|false +|false +| +|"native" +|{ +"password": "*********", +"changeRequired": false +} +|"jack" +|["PUBLIC"] +|false +|false +| +|"oidc1" +|{ +"id": "jacksIdForOidc1" +} +7+a|Rows: 3 +|=== +====== + +.Show user with auth using filtering +====== +Show all users with the `oidc` auth provider. +[source,cypher,role=noplay] +---- +SHOW USERS WITH AUTH +WHERE provider = 'oidc1' +---- + +.Result +[role="queryresult" options="header,footer", width="100%", cols="2m,3m,3m,2m,2m,3m,4m"] +|=== +|user +|roles +|passwordChangeRequired +|suspended +|home +|provider +|auth +|"jack" +|["PUBLIC"] +|false +|false +| +|"oidc1" +|{ +"id": "jacksIdForOidc1" +} +7+a|Rows: 1 +|=== + +====== + +For more information about auth providers, see xref:authentication-authorization/auth-providers.adoc[User auth providers]. + +[[access-control-create-users]] +== Creating users + +You can create users using one of the following Cypher commands, depending on whether you want to create a new user or replace an existing one. +In both cases, you can specify the user's password, whether they must change it at the next login, their status, home database, and auth provider settings. +The `SET` clauses can be applied in any order. +It is mandatory to specify a `SET PASSWORD` and/or at least one `SET AUTH` clause because users must have at least one auth provider. +`SET AUTH` is available from Neo4j 5.24 onwards. + +.`CREATE USER` syntax +[source, syntax, role="noheader"] +---- +CREATE USER name [IF NOT EXISTS] # <1> + [SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password'] # <2> + [[SET PASSWORD] CHANGE [NOT] REQUIRED] # <3> + [SET STATUS {ACTIVE \| SUSPENDED}] # <4> + [SET HOME DATABASE name] # <5> + [SET AUTH [PROVIDER] 'provider' "{"{SET }..."}"]... # <6> +---- + +.`CREATE OR REPLACE USER` syntax +[source, syntax, role="noheader"] +---- +CREATE OR REPLACE USER name # <1> + [SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password'] # <2> + [[SET PASSWORD] CHANGE [NOT] REQUIRED] # <3> + [SET STATUS {ACTIVE \| SUSPENDED}] # <4> + [SET HOME DATABASE name] # <5> + [SET AUTH [PROVIDER] 'provider' "{"{SET }..."}"]... # <6> +---- +Where: + +<1> Specifies the command to create a user. +<2> Specifies the password for the user. +The `'password'` can either be a string value or a string parameter with default value length of at least 8 characters. + +The `PLAINTEXT` and `ENCRYPTED` keywords are optional and can be used to specify the format of the password, i.e. whether Neo4j needs to hash it or it has already been hashed. +By default, all passwords are encrypted (hashed) when stored in the Neo4j `system` database. +* The optional `PLAINTEXT` in `SET PLAINTEXT PASSWORD` has the same behavior as `SET PASSWORD`. +* The optional `ENCRYPTED` is used to recreate an existing user when the plaintext password is unknown, but the encrypted password is available in the _data/databases/databasename/tools/metadata_script.cypher_ file of a database backup. +See xref:backup-restore/restore-backup#_restore_users_and_roles_metadata[Restore users and roles metadata]. + +With `ENCRYPTED`, the password string is expected to be in the format of `,,`, where, for example: +** `0` is the first version and refers to the `SHA-256` cryptographic hash function with iterations `1`. +** `1` is the second version and refers to the `SHA-256` cryptographic hash function with iterations `1024`. + +<3> Specifies whether the user must change their password at the next login. +If the optional `SET PASSWORD CHANGE [NOT] REQUIRED` is omitted but a password is given, the default is `CHANGE REQUIRED`. +The `SET PASSWORD` prefix of the `CHANGE [NOT] REQUIRED` clause is only optional if it directly follows the `SET PASSWORD 'password'` clause and is not part of a `SET AUTH` clause. + +<4> Specifies the user's status. +If not set, the default is `ACTIVE`. + +<5> Specifies a home database for a user. +A home database is resolved if it is pointing to a database or a database alias. +If no home database is set, the DBMS default database is used as the home database for that user. + +<6> label:new[Introduced in 5.24] One or more `SET AUTH` clause can be used to configure external xref:authentication-authorization/auth-providers.adoc[auth providers], such as LDAP or OIDC, which define authentication/authorization providers for that user. +`SET AUTH` can also be used as an alternative way to set the native (password-based) auth settings like `SET PASSWORD` and `SET PASSWORD CHANGE REQUIRED`. +For further informations, see the examples in this section, as well as xref:authentication-authorization/sso-integration.adoc#auth-sso-auth-providers[Configure SSO at the user level using auth providers] for OIDC, and xref:authentication-authorization/ldap-integration.adoc#auth-ldap-auth-providers[Configure authentication/authorization at the user level using auth providers] for LDAP. ++ +[source, syntax, role="noheader"] +---- +SET AUTH [PROVIDER] 'provider' "{" + { + SET ID 'id' # a unique identifier of the user in an external system. + \| SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password' # only applicable to the 'native' provider. + \| SET PASSWORD CHANGE [NOT] REQUIRED # only applicable to the 'native' provider. + } +"}" +---- + +[NOTE] +==== +Usernames are case sensitive. +The created user will appear on the list provided by `SHOW USERS`. + +* In Neo4j Community Edition there are no roles, but all users have implied administrator privileges. +* In Neo4j Enterprise Edition all users are automatically assigned the xref:authentication-authorization/built-in-roles.adoc#access-control-built-in-roles-public[`PUBLIC` role], giving them a base set of privileges. +==== + + +.Create user +====== +For example, you can create the user `jake` in a suspended state, with the home database `anotherDb`, and the requirement to change the password by using the command: + +[source,cypher,role=noplay] +---- +CREATE USER jake +SET PASSWORD 'abcd1234' CHANGE REQUIRED +SET STATUS SUSPENDED +SET HOME DATABASE anotherDb +---- + +[role=label--new-5.24] +The equivalent command using the xref:authentication-authorization/auth-providers.adoc[auth providers] syntax would be: + +[source,cypher,role=noplay] +---- +CREATE USER jake +SET STATUS SUSPENDED +SET HOME DATABASE anotherDb +SET AUTH 'native' {SET PASSWORD 'abcd1234' SET PASSWORD CHANGE REQUIRED} +---- +====== + + +.Create user with an encrypted password +====== +Or you can create the user `Jake` in an active state, with an encrypted password (taken from the _data/databases/databasename/tools/metadata_script.cypher_ of a database backup), and the requirement to not change the password by running: + +[source,cypher,role=noplay] +---- +CREATE USER Jake +SET ENCRYPTED PASSWORD '1,6d57a5e0b3317055454e455f96c98c750c77fb371f3f0634a1b8ff2a55c5b825,190ae47c661e0668a0c8be8a21ff78a4a34cdf918cae3c407e907b73932bd16c' CHANGE NOT REQUIRED +SET STATUS ACTIVE +---- + +[role=label--new-5.24] +The equivalent command using the xref:authentication-authorization/auth-providers.adoc[auth providers] syntax would be: +. +[source,cypher,role=noplay] +---- +CREATE USER jake +SET STATUS ACTIVE +SET AUTH 'native' { + SET ENCRYPTED PASSWORD '1,6d57a5e0b3317055454e455f96c98c750c77fb371f3f0634a1b8ff2a55c5b825,190ae47c661e0668a0c8be8a21ff78a4a34cdf918cae3c407e907b73932bd16c' + SET PASSWORD CHANGE NOT REQUIRED +} +---- + +====== + +[NOTE, role=label--enterprise-edition] +==== +The `SET STATUS {ACTIVE | SUSPENDED}`, `SET HOME DATABASE` parts of the commands are only available in Neo4j Enterprise Edition. +The `SET AUTH` clause for external providers is only available in Neo4j Enterprise Edition. +However, `SET AUTH 'native'` can be used in Neo4j Community Edition. +==== + +The `CREATE USER` command is optionally idempotent, with the default behavior to throw an exception if the user already exists. +Appending `IF NOT EXISTS` to the `CREATE USER` command will ensure that no exception is thrown and nothing happens should the user already exist. + + +.Create user if not exists +====== +[source,cypher,role=noplay] +---- +CREATE USER jake IF NOT EXISTS +SET PLAINTEXT PASSWORD 'abcd1234' +---- + +[role=label--new-5.24] +The equivalent command using the xref:authentication-authorization/auth-providers.adoc[auth providers] syntax would be: + +[source,cypher,role=noplay] +---- +CREATE USER jake IF NOT EXISTS +SET AUTH 'native' {SET PLAINTEXT PASSWORD 'abcd1234'} +---- +====== + +The `CREATE OR REPLACE USER` command will result in any existing user being deleted and a new one created. + + +.Create or replace user +====== +[source,cypher,role=noplay] +---- +CREATE OR REPLACE USER jake +SET PLAINTEXT PASSWORD 'abcd1234' +---- + +This is equivalent to running `DROP USER jake IF EXISTS` followed by `CREATE USER jake SET PASSWORD 'abcd1234'`. + +[role=label--new-5.24] +The equivalent command using the xref:authentication-authorization/auth-providers.adoc[auth providers] syntax would be: + +[source,cypher,role=noplay] +---- +CREATE OR REPLACE USER jake +SET AUTH 'native' {SET PLAINTEXT PASSWORD 'abcd1234'} +---- +====== + +[NOTE] +==== +The `CREATE OR REPLACE USER` command does not allow the use of `IF NOT EXISTS`. +==== + + +[[access-control-rename-users]] +== Renaming users + +Users can be renamed with the `RENAME USER` command. + +[source, cypher, role=noplay] +---- +RENAME USER jake TO bob +---- + +To verify the change, you can use the `SHOW USERS` command: + +[source, cypher, role=noplay] +---- +SHOW USERS +---- + +.Result +[options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user |roles |passwordChangeRequired |suspended |home + +|"bob" +|["PUBLIC"] +|true +|false +| + +|"neo4j" +|["admin","PUBLIC"] +|true +|false +| + +5+a|Rows: 2 + +|=== + +[NOTE] +==== +The `RENAME USER` command is only available when using native authentication and authorization. +==== + + +[[access-control-alter-users]] +== Modifying users + +You can modify users with the `ALTER USER` command. +The command allows you to change the user's password, status, home database, and auth provider settings. +The `SET` and `REMOVE` clauses can be applied in any order. +However, all `REMOVE` clauses must come before the first `SET` clause and at least one `SET` or `REMOVE` clause is required for the command. +If any of the `SET` or `REMOVE` clauses are omitted, the corresponding settings will not be changed. + +[source, syntax, role="noheader"] +---- +ALTER USER name [IF EXISTS] # <1> + [REMOVE HOME DATABASE] # <2> + [REMOVE { AUTH [PROVIDER[S]] provider[, ...] \| ALL AUTH [PROVIDER[S]] }]... # <3> + [SET [PLAINTEXT | ENCRYPTED] PASSWORD 'password'] # <4> + [[SET PASSWORD] CHANGE [NOT] REQUIRED] # <5> + [SET STATUS {ACTIVE | SUSPENDED}] # <6> + [SET HOME DATABASE name] # <7> + [SET AUTH [PROVIDER] 'provider' "{"{SET }..."}"]... # <8> +---- +Where: + +<1> Specifies the command to alter a user. +<2> Removes the home database for the user. +As a result, the DBMS default database will be used as the home database for that user. +<3> label:new[Introduced in 5.24] Removes one, several, or all existing xref:authentication-authorization/auth-providers.adoc[auth provider(s)] from a user. +However, a user must always have at least one auth provider. +Therefore, `REMOVE ALL AUTH` must be used in conjunction with at least one `SET AUTH` clause in order to meet this requirement. +<4> Specifies the password for the user. +The `'password'` can either be a string value or a string parameter with default value length of at least 8 characters. + +The `PLAINTEXT` and `ENCRYPTED` keywords are optional and can be used to specify the format of the password, i.e. whether Neo4j needs to hash it or it has already been hashed. +By default, all passwords are encrypted (hashed) when stored in the Neo4j `system` database. +* The optional `PLAINTEXT` in `SET PLAINTEXT PASSWORD` has the same behavior as `SET PASSWORD`. +* The optional `ENCRYPTED` is used to recreate an existing user when the plaintext password is unknown, but the encrypted password is available in the _data/databases/databasename/tools/metadata_script.cypher_ file of a database backup. +See xref:backup-restore/restore-backup#_restore_users_and_roles_metadata[Restore users and roles metadata]. + +With `ENCRYPTED`, the password string is expected to be in the format of `,,`, where, for example: +** `0` is the first version and refers to the `SHA-256` cryptographic hash function with iterations `1`. +** `1` is the second version and refers to the `SHA-256` cryptographic hash function with iterations `1024`. +<5> Specifies whether the user must change their password at the next login. +If the optional `SET PASSWORD CHANGE [NOT] REQUIRED` is omitted when adding native auth to a user (either by first removing pre-existing native auth or if the user does not have native auth to start with), the default is `CHANGE REQUIRED`. +The `SET PASSWORD` prefix of the `CHANGE [NOT] REQUIRED` clause is only optional if it directly follows the `SET PASSWORD 'password'` clause and is not part of a `SET AUTH` clause. +<6> Specifies the user's status. +<7> Specifies a home database for a user. A home database is resolved if it is pointing to a database or a database alias. If no home database is set, the DBMS default database is used as the home database for that user. + +<8> label:new[Introduced in 5.24] One or more `SET AUTH` clauses can be used to set xref:authentication-authorization/auth-providers.adoc[auth providers], which define authentication / authorization providers for that user. +This might be used to configure external auth providers like LDAP or OIDC, but can also be used as an alternative way to set the native (password-based) auth settings like `SET PASSWORD` and `SET PASSWORD CHANGE REQUIRED`. +For further informations, see the examples in this section, as well as xref:authentication-authorization/sso-integration.adoc#auth-sso-auth-providers[Configure SSO at the user level using auth providers], and xref:authentication-authorization/ldap-integration.adoc#auth-ldap-auth-providers[Configure authentication/authorization at the user level using auth providers]. ++ +[source, syntax, role="noheader"] +---- +SET AUTH [PROVIDER] 'provider' "{" + { + SET ID 'id' # a unique identifier of the user in an external system + \| SET [PLAINTEXT \| ENCRYPTED] PASSWORD 'password' # only applicable to the 'native' provider + \| SET PASSWORD CHANGE [NOT] REQUIRED # only applicable to the 'native' provider + } +"}" +---- + + +.Modify a user's password and status +====== +For example, you can modify the user `bob` by setting a new password and active status, and removing the requirement to change his password by running: + +[source,cypher,role=noplay] +---- +ALTER USER bob +SET PASSWORD 'abcd5678' CHANGE NOT REQUIRED +SET STATUS ACTIVE +---- + +[role=label--new-5.24] +The equivalent command using the xref:authentication-authorization/auth-providers.adoc[auth providers] syntax would be: + +---- +ALTER USER bob +SET AUTH 'native' {SET PASSWORD 'abcd5678' SET PASSWORD CHANGE NOT REQUIRED} +SET STATUS ACTIVE +---- +====== + +.Modify a user to expire their current password +====== +For example, you can modify the user `bob` to expire his current password so that he must change it the next time he logs in: + +[source,cypher,role=noplay] +---- +ALTER USER bob +SET PASSWORD CHANGE REQUIRED +---- + +[role=label--new-5.24] +The equivalent command using the xref:authentication-authorization/auth-providers.adoc[auth providers] syntax would be: + +---- +ALTER USER bob +SET AUTH 'native' {SET PASSWORD CHANGE REQUIRED} +---- +====== + +[role=label--enterprise-edition label--new-5.24] +.Modify a user to use an external OIDC auth provider +====== +For example, you can modify the user `bob` by removing his native auth provider and adding an external OIDC auth provider: + +[source,cypher,role=noplay] +---- +ALTER USER bob +REMOVE AUTH 'native' +SET AUTH 'oidc-mysso1' {SET ID 'bobsUniqueMySso1Id'} +---- +====== + +[role=label--enterprise-edition label--new-5.24] +.Modify a user to use multiple external OIDC auth providers +====== +For example, you can modify the user `bob` by removing all of his existing auth providers and adding two external OIDC auth providers: + +[source,cypher,role=noplay] +---- +ALTER USER bob +REMOVE ALL AUTH +SET AUTH 'oidc-mysso1' {SET ID 'bobsUniqueMySso1Id'} +SET AUTH 'oidc-mysso2' {SET ID 'bobsUniqueMySso2Id'} +---- +====== + +.Assign a user a different home database +====== +For example, you can modify the user `bob` by assigning him a different home database: + +[source,cypher,role=noplay] +---- +ALTER USER bob +SET HOME DATABASE anotherDbOrAlias +---- +====== + +.Remove the home database from a user and set their status to suspended +====== +For example, you can modify the user `bob` by removing his home database and setting his status to suspended: + +[source,cypher,role=noplay] +---- +ALTER USER bob +REMOVE HOME DATABASE +SET STATUS SUSPENDED +---- +====== + +[NOTE] +==== +When altering a user, it is only necessary to specify the changes required. +For example, leaving out the `CHANGE [NOT] REQUIRED` part of the query leaves that unchanged. +==== + +[NOTE, role=label--enterprise-edition] +==== +The `SET STATUS {ACTIVE | SUSPENDED}`, `SET HOME DATABASE`, `REMOVE HOME DATABASE`, and `REMOVE AUTH` parts of the command are only available in Neo4j Enterprise Edition. +The `SET AUTH` clause for external providers is only available in Neo4j Enterprise Edition. +However, `SET AUTH 'native'` can be used in Neo4j Community Edition. +==== + +The changes to the user will appear on the list provided by `SHOW USERS`: + +[source, cypher, role=noplay] +---- +SHOW USERS +---- + +.Result +[options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user |roles |passwordChangeRequired |suspended |home + +|"bob" +|["PUBLIC"] +|false +|false +| + +|"neo4j" +|["admin","PUBLIC"] +|true +|false +| + +5+a|Rows: 2 + +|=== + +The default behavior of this command is to throw an exception if the user does not exist. +Adding an optional parameter `IF EXISTS` to the command makes it idempotent and ensures that no exception is thrown. +Nothing happens should the user not exist. + +[source, cypher, role=noplay] +---- +ALTER USER nonExistingUser IF EXISTS SET PASSWORD 'abcd1234' +---- + + +[[access-control-alter-password]] +== Changing the current user's password + +Users can change their password using `ALTER CURRENT USER SET PASSWORD`. +The old password is required in addition to the new one, and either or both can be a string value or a string parameter. +When a user executes this command it will change their password as well as set the `CHANGE NOT REQUIRED` flag. + +// can't test, don't want to hardcode test user password +[source, cypher, role=test-skip] +---- +ALTER CURRENT USER +SET PASSWORD FROM 'password1' TO 'password2' +---- + +[NOTE] +==== +This command works only for a logged-in user and cannot be run with auth disabled. +==== + + +[[access-control-drop-users]] +== Delete users + +Users can be deleted with `DROP USER`. + +[source, cypher, role=noplay] +---- +DROP USER bob +---- + +Deleting a user does not automatically terminate associated connections, sessions, transactions, or queries. + +However, when a user is deleted, it no longer appears on the list provided by `SHOW USERS`: + +[source, cypher, role=noplay] +---- +SHOW USERS +---- + +.Result +[options="header,footer", width="100%", cols="2m,3m,3m,2m,2m"] +|=== +|user |roles |passwordChangeRequired |suspended |home + +|"neo4j" +|["admin","PUBLIC"] +|true +|false +| + +5+a|Rows: 1 + +|=== diff --git a/modules/ROOT/pages/authentication-authorization/password-and-user-recovery.adoc b/modules/ROOT/pages/authentication-authorization/password-and-user-recovery.adoc new file mode 100644 index 000000000..16f2b7f6b --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/password-and-user-recovery.adoc @@ -0,0 +1,255 @@ +:description: This page describes how to reset a password to recover a user's access when their password is lost. It specifically focuses on how to recover an admin user if all the admin users have been unassigned the admin role, and how to recreate the built-in admin role if it has been dropped. +[[password-and-user-recovery]] += Recover admin user and password + +This page describes how to reset a password to recover a user's access when their password is lost. +It specifically focuses on how to recover an admin user if all the admin users have been unassigned the admin role, and how to recreate the built-in admin role if it has been dropped. + +[[disable-authentication]] +== Disable authentication + +[.tabbed-example] +===== +[.include-with-standalone] +====== + +. Stop Neo4j: ++ +[source, shell] +---- +bin/neo4j stop +---- +. Open the _neo4j.conf_ file and set `dbms.security.auth_enabled` parameter to `false` to disable the authentication: ++ +[source, properties] +---- +dbms.security.auth_enabled=false +---- + +. Block network connections during the recovery phase, so users can connect to Neo4j only via `localhost`. +This can be achieved by temporarily commenting out the `server.default_listen_address` parameter and providing the specific localhost value: ++ +[source, properties] +---- +server.default_listen_address=127.0.0.1 +---- ++ +[NOTE] +==== +Ensure, you have blocked all network connections for any individual services configured to listen to `listen_addresses`. +==== ++ +. Start Neo4j: ++ +[source, shell] +---- +bin/neo4j start +---- +====== +[.include-with-cluster] +====== +. Stop all members of the cluster: ++ +[source, shell] +---- +bin/neo4j stop +---- ++ +. On each member, open the _neo4j.conf_ file and modify the following settings: +.. Set `dbms.security.auth_enabled` parameter to `false` to disable the authentication: ++ +[source, properties] +---- +dbms.security.auth_enabled=false +---- ++ +.. Disable the HTTP and HTTPS network connections and restrict the `bolt` connector to use only `localhost`. +Set `server.http.enabled` to `false`. +This ensures that no one from outside can access the cluster during the recovery period. ++ +[source, properties] +---- +server.http.enabled=false +#server.https.enabled=true +server.bolt.listen_address:127.0.0.1 +---- ++ +. Start all members of the cluster: ++ +[source, shell] +---- +bin/neo4j start +---- +====== +===== + +[[password-recovery-for-admin]] +== Recover a lost password + +You can use a client such as xref:tools/cypher-shell.adoc[Cypher Shell] or the Neo4j Browser to connect to the xref:database-administration/index.adoc#manage-databases-system[`system`] database and set a new password for the admin user. + +[NOTE] +==== +In a cluster deployment, you should complete the steps only on one of the cluster members. +==== + +. Complete the steps in xref:authentication-authorization/password-and-user-recovery.adoc#disable-authentication[Disable authentication] as per your deployment. +. Connect to the `system` database using Cypher shell. +Alternatively, log into Neo4j Browser. ++ +[source, shell] +---- +bin/cypher-shell -d system +---- ++ +[NOTE, role=label--cluster] +==== +If you have specified a non-default port for your `bolt` connector, add `-a neo4j://:` to the `cypher-shell` command to be able to connect to your cluster member. +==== +. Set a new password for the admin user. +In this example, the admin user is named `neo4j`. ++ +[source, cypher] +---- +ALTER USER neo4j SET PASSWORD 'mynewpassword' +---- +. Exit the `cypher-shell` console: ++ +[source, shell] +---- +:exit; +---- +. Proceed with the xref:authentication-authorization/password-and-user-recovery.adoc#post-recovery[post-recovery steps] as per your deployment. + +[[recover-unassigned-admin-role]] +== Recover an unassigned admin role + +You can use a client such as xref:tools/cypher-shell.adoc[Cypher Shell] or the Neo4j Browser to connect to the xref:database-administration/index.adoc#manage-databases-system[`system`] database and grant the admin user role to an existing user. + +[NOTE] +==== +In a cluster deployment, you should complete the steps only on one of the cluster members. +==== + +. Complete the steps in xref:authentication-authorization/password-and-user-recovery.adoc#disable-authentication[Disable authentication] as per your deployment. +. Connect to the `system` database using Cypher shell. +Alternatively, log into Neo4j Browser. ++ +[source, shell] +---- +bin/cypher-shell -d system +---- ++ +[NOTE, role=label--cluster] +==== +If you have specified a non-default port for your `bolt` connector, add `-a neo4j://:` to the `cypher-shell` command to be able to connect to your cluster member. +==== +. Grant the admin user role to an existing user. +In this example, the user is named `neo4j`. ++ +[source, cypher] +---- +GRANT ROLE admin TO neo4j +---- +. Exit the `cypher-shell` console: ++ +[source, shell] +---- +:exit; +---- +. Proceed with the xref:authentication-authorization/password-and-user-recovery.adoc#post-recovery[post-recovery steps] as per your deployment. + +[[recover-admin-role]] +== Recover the admin role + +If you have removed the admin role from your system entirely, you can use a client such as xref:tools/cypher-shell.adoc[Cypher Shell] or the Neo4j Browser to connect to the xref:database-administration/index.adoc#manage-databases-system[`system`] database and recreate the role with its original capabilities. + +[NOTE] +==== +In a cluster deployment, you should complete the steps only on one of the cluster members. +==== + +. Complete the steps in xref:authentication-authorization/password-and-user-recovery.adoc#disable-authentication[Disable authentication] as per your deployment. +. Connect to the `system` database using Cypher shell. +Alternatively, log into Neo4j Browser. ++ +[source, shell] +---- +bin/cypher-shell -d system +---- ++ +[role=label--cluster] +[NOTE] +==== +If you have specified a non-default port for your `bolt` connector, add `-a neo4j://:` to the `cypher-shell` command to be able to connect to your cluster member. +==== +. Recreate the admin role with its original capabilities. ++ +[source, cypher] +---- +CREATE ROLE admin; +GRANT ALL DBMS PRIVILEGES ON DBMS TO admin; +GRANT TRANSACTION MANAGEMENT ON DATABASE * TO admin; +GRANT START ON DATABASE * TO admin; +GRANT STOP ON DATABASE * TO admin; +GRANT MATCH {*} ON GRAPH * TO admin; +GRANT WRITE ON GRAPH * TO admin; +GRANT ALL ON DATABASE * TO admin; +---- +. Grant the admin user role to an existing user. ++ +[NOTE] +==== +Before running the `:exit` command, we suggest granting the newly created role to a user. +Although this is optional, without this step you will have only collected all admin privileges in a role that no one is assigned to. + +To grant the role to a user (assuming your existing user is named `neo4j`), you can run `GRANT ROLE admin TO neo4j;` +==== +. Exit the `cypher-shell` console: ++ +[source, shell] +---- +:exit; +---- +. Proceed with the xref:authentication-authorization/password-and-user-recovery.adoc#post-recovery[post-recovery steps] as per your deployment. + +[[post-recovery]] +== Post-recovery steps + +[.tabbed-example] +===== +[.include-with-standalone] +====== + +. Stop Neo4j: ++ +[source, shell] +---- +bin/neo4j stop +---- +. Enable the authentication and restore your Neo4j to its original configuration (See xref:authentication-authorization/password-and-user-recovery.adoc#disable-authentication[Disable authentication]). +. Start Neo4j: ++ +[source, shell] +---- +bin/neo4j start +---- +====== +[.include-with-cluster] +====== +. Stop the cluster members. ++ +[source, shell] +---- +bin/neo4j stop +---- ++ +. Enable the authentication and restore each cluster member to its original configuration (See xref:authentication-authorization/password-and-user-recovery.adoc#disable-authentication[Disable authentication]). +. Start the cluster (all cluster members): ++ +[source, shell] +---- +bin/neo4j start +---- +====== +===== diff --git a/modules/ROOT/pages/authentication-authorization/privileges-reads.adoc b/modules/ROOT/pages/authentication-authorization/privileges-reads.adoc new file mode 100644 index 000000000..1b37465cc --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/privileges-reads.adoc @@ -0,0 +1,241 @@ +:description: How to use Cypher to manage read privileges on graphs. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated +//// +[source, cypher, role=test-setup] +---- +CREATE ROLE regularUsers; +---- +//// + + +[[access-control-privileges-reads]] += Read privileges + +There are three separate read privileges: + +* xref:authentication-authorization/privileges-reads.adoc#access-control-privileges-reads-traverse[`TRAVERSE`] - enables the specified entities to be found. +* xref:authentication-authorization/privileges-reads.adoc#access-control-privileges-reads-read[`READ`] - enables the specified properties of the found entities to be read. +* xref:authentication-authorization/privileges-reads.adoc#access-control-privileges-reads-match[`MATCH`] - combines both `TRAVERSE` and `READ`, enabling an entity to be found and its properties read. + +For more details about how to read the administration commands syntax, see xref:database-administration/syntax.adoc#administration-syntax-reading[Reading the administration commands syntax] and xref:authentication-authorization/manage-privileges.adoc#components-of-the-graph-privilege-commands[Components of the graph privilege commands]. + +[[access-control-privileges-reads-traverse]] +== The `TRAVERSE` privilege + +Users can be granted the right to find nodes and relationships using the `GRANT TRAVERSE` privilege. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] TRAVERSE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + | FOR pattern + ] + TO role[, ...] +---- + +[NOTE] +==== +For more details about the `pattern` syntax used to express attributes based access control rules, see xref:authentication-authorization/property-based-access-control.adoc[Property-based access control]. +==== + +For example, you can enable users with the role `regularUsers` to find all nodes with the label `Post` in the database `neo4j`: + +[source, cypher, role=noplay] +---- +GRANT TRAVERSE ON GRAPH neo4j NODES Post TO regularUsers +---- + +The `TRAVERSE` privilege can also be denied. + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] TRAVERSE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + | FOR pattern + ] + TO role[, ...] +---- + +For example, we can disable users with the role `regularUsers` from finding all nodes with the label `Payments`: + +[source, cypher, role=noplay] +---- +DENY TRAVERSE ON HOME GRAPH NODES Payments TO regularUsers +---- + +Although you just granted the role `regularUsers` the right to read all properties on nodes with label `Post`, you may want to make this more fine-grained using xref:authentication-authorization/property-based-access-control.adoc[Property-based access control] to hide the posts with `secret` property set to `true`. +For example: + +[source, cypher, role=noplay] +---- +DENY TRAVERSE ON HOME GRAPH FOR (:Post {secret: true}) TO regularUsers +---- + +[NOTE] +==== +If a label or a relationship type does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-reads-read]] +== The `READ` privilege + +Users can be granted the right to do property reads on nodes and relationships using the `GRANT READ` privilege. +It is very important to note that users can only read properties on entities that they are enabled to find in the first place. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] READ "{" { * | property[, ...] } "}" + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + | FOR pattern + ] + TO role[, ...] +---- +[NOTE] +==== +For more details about the `pattern` syntax used to express attributes based access control rules, see xref:authentication-authorization/property-based-access-control.adoc[Property-based access control]. +==== + +For example, you can enable users with the role `regularUsers` to read all properties on nodes with the label `Post` in the database `neo4j`. +The `+*+` implies that the ability to read all properties also extends to properties that might be added in the future. + +[source, cypher, role=noplay] +---- +GRANT READ { * } ON GRAPH neo4j NODES Post TO regularUsers +---- + +To further fine-grained the read access, you can enable users with the role `regularUsers` to read all properties on nodes with the label `Post` that have property `secret` not set to `true` in the database `neo4j`. +For example: + +[source, cypher, role=noplay] +---- +GRANT READ { * } ON GRAPH neo4j FOR (n:Post) WHERE n.secret <> true TO regularUsers +---- + +[NOTE] +==== +Granting property `READ` access does not imply that the entities with that property can be found. +For example, if there is also a `DENY TRAVERSE` present on the same entity as a `GRANT READ`, the entity will not be found by a Cypher `MATCH` statement. +==== + +The `READ` privilege can also be denied. + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] READ "{" { * | property[, ...] } "}" + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + | FOR pattern + ] + TO role[, ...] +---- + +Although we just granted the role `regularUsers` the right to read all properties, we may want to hide the `secret` property. +The following example shows how to do that: + +[source, cypher, role=noplay] +---- +DENY READ { secret } ON GRAPH neo4j NODES Post TO regularUsers +---- + +[NOTE] +==== +If a label, a relationship type, or a property name does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-reads-match]] +== The `MATCH` privilege + +Users can be granted the right to find and do property reads on nodes and relationships using the `GRANT MATCH` privilege. +This is semantically the same as having both `TRAVERSE` and `READ` privileges. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] MATCH "{" { * | property[, ...] } "}" + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + | FOR pattern + ] + TO role[, ...] +---- +[NOTE] +==== +For more details about the `pattern` syntax used to express attributes based access control rules, see xref:authentication-authorization/property-based-access-control.adoc[Property-based access control]. +==== + +For example if you want to grant the ability to read the properties `language` and `length` for nodes with the label `Message`, as well as the ability to find these nodes to the role `regularUsers`, you can use the following `GRANT MATCH` query: + +[source, cypher, role=noplay] +---- +GRANT MATCH { language, length } ON GRAPH neo4j NODES Message TO regularUsers +---- + +The following query grants the `regularUsers` role the ability to find `Post` and `Likes` nodes where the `secret` property is set to `false`, as well as reading all their properties. + +[source, cypher, role=noplay] +---- +GRANT MATCH { * } ON GRAPH neo4j FOR (n:Post|Likes) WHERE n.secret = false TO regularUsers +---- + +Like all other privileges, the `MATCH` privilege can also be denied. + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] MATCH "{" { * | property[, ...] } "}" + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + | FOR pattern + ] + TO role[, ...] +---- + +Please note that the effect of denying a `MATCH` privilege depends on whether concrete property keys are specified or are `+*+`. +If you specify concrete property keys, then `DENY MATCH` will only deny reading those properties. +Finding the elements to traverse would still be enabled. +If you specify `+*+` instead, then both traversal of the element and all property reads will be disabled. +The following queries will show examples for this. + +Denying to read the property `content` on nodes with the label `Message` for the role `regularUsers` would look like the following query. +Although not being able to read this specific property, nodes with that label can still be traversed (and, depending on other grants, other properties on it could still be read). + +[source, cypher, role=noplay] +---- +DENY MATCH { content } ON GRAPH neo4j NODES Message TO regularUsers +---- + +The following query exemplifies how it would look if you wanted to deny both reading all properties and traversing nodes labeled with `Account` in the database `neo4j`: + +[source, cypher, role=noplay] +---- +DENY MATCH { * } ON GRAPH neo4j NODES Account TO regularUsers +---- + +[NOTE] +==== +If a label, a relationship type, or a property name does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== diff --git a/modules/ROOT/pages/authentication-authorization/privileges-writes.adoc b/modules/ROOT/pages/authentication-authorization/privileges-writes.adoc new file mode 100644 index 000000000..ee5349e7d --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/privileges-writes.adoc @@ -0,0 +1,441 @@ +:description: How to use Cypher to manage write privileges on graphs. +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated + +//// +[source, cypher, role=test-setup] +---- +CREATE ROLE regularUsers; +---- +//// + +[[access-control-privileges-writes]] += Write privileges + +Write privileges are defined for different parts of the graph: + +* <> - allows creating nodes and relationships. +* <> - allows deleting nodes and relationships. +* <> - allows setting the specified node labels using the `SET` clause. +* <> - allows removing the specified node labels using the `REMOVE` clause. +* <> - allows setting properties on nodes and relationships. + +There are also compound privileges that combine the above specific privileges: + +* <> - allows `MATCH`, `CREATE`, and `SET PROPERTY` to apply the `MERGE` command. +* <> - allows all `WRITE` operations on an entire graph. +* <> - allows all `READ` and `WRITE` operations on an entire graph. + +For more details about how to read the administration commands syntax, see xref:database-administration/syntax.adoc#administration-syntax-reading[Reading the administration commands syntax] and xref:authentication-authorization/manage-privileges.adoc#components-of-the-graph-privilege-commands[Components of the graph privilege commands]. + +[[access-control-privileges-writes-create]] +== The `CREATE` privilege + +The `CREATE` privilege allows a user to create new node and relationship elements on a graph. +For more details, see link:{neo4j-docs-base-uri}/cypher-manual/5/clauses/create/[the Cypher Manual -> `CREATE`] clause. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] CREATE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + ] + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to `CREATE` elements on the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT CREATE ON GRAPH neo4j ELEMENTS * TO regularUsers +---- + +The `CREATE` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] CREATE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + ] + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to `CREATE` nodes with the label `foo` on all graphs, use: + +[source, cypher, role=noplay] +---- +DENY CREATE ON GRAPH * NODES foo TO regularUsers +---- + +[NOTE] +==== +If the user attempts to create nodes with a label that does not already exist on the database, then the user must also possess the xref:authentication-authorization/database-administration.adoc#access-control-database-administration-tokens[`CREATE NEW LABEL`] privilege. +The same applies to new relationships: the xref:authentication-authorization/database-administration.adoc#access-control-database-administration-tokens[`CREATE NEW RELATIONSHIP TYPE`] privilege is required. +==== + +[NOTE] +==== +If a label or a relationship type does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-writes-delete]] +== The `DELETE` privilege + +The `DELETE` privilege allows a user to delete node and relationship elements on a graph. +For more details, see link:{neo4j-docs-base-uri}/cypher-manual/5/clauses/delete/[the Cypher Manual -> `DELETE`] clause. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] DELETE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + ] + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to `DELETE` elements on the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT DELETE ON GRAPH neo4j ELEMENTS * TO regularUsers +---- + +The `DELETE` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] DELETE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + ] + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to `DELETE` relationships with the relationship type `bar` on all graphs, use: + +[source, cypher, role=noplay] +---- +DENY DELETE ON GRAPH * RELATIONSHIPS bar TO regularUsers +---- + +[NOTE] +==== +Users with `DELETE` privilege, but restricted `TRAVERSE` privileges, will not be able to do `DETACH DELETE` in all cases. +See xref:tutorial/access-control.adoc#detach-delete-restricted-user[delete restricted user] for more info. +==== + +[NOTE] +==== +If a label or a relationship type does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-writes-set-label]] +== The `SET LABEL` privilege + +The `SET LABEL` privilege allows you to set labels on a node using the link:{neo4j-docs-base-uri}/cypher-manual/5/clauses/set/#set-set-a-label-on-a-node[Cypher `SET` clause]: + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] SET LABEL { * | label[, ...] } + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to `SET` any label on nodes of the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT SET LABEL * ON GRAPH neo4j TO regularUsers +---- + +[NOTE] +==== +Unlike many of the other `READ` and `WRITE` privileges, it is not possible to restrict the `SET LABEL` privilege to specific +ELEMENTS+, +NODES+ or +RELATIONSHIPS+. +==== + +The `SET LABEL` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] SET LABEL { * | label[, ...] } + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to `SET` the label `foo` on nodes of all graphs, use: + +[source, cypher, role=noplay] +---- +DENY SET LABEL foo ON GRAPH * TO regularUsers +---- + +[NOTE] +==== +If no instances of this label exist on the database, then the xref:authentication-authorization/database-administration.adoc#access-control-database-administration-tokens[`CREATE NEW LABEL`] privilege is also required. +==== + +[NOTE] +==== +If a label does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-writes-remove-label]] +== The `REMOVE LABEL` privilege + +The `REMOVE LABEL` privilege allows you to remove labels from a node by using the link:{neo4j-docs-base-uri}/cypher-manual/5/clauses/remove/#remove-remove-a-label-from-a-node[Cypher `REMOVE` clause]: + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] REMOVE LABEL { * | label[, ...] } + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to `REMOVE` any label from nodes of the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT REMOVE LABEL * ON GRAPH neo4j TO regularUsers +---- + +[NOTE] +==== +Unlike many of the other `READ` and `WRITE` privileges, it is not possible to restrict the `REMOVE LABEL` privilege to specific +ELEMENTS+, +NODES+ or +RELATIONSHIPS+. +==== + +The `REMOVE LABEL` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] REMOVE LABEL { * | label[, ...] } + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, denying the role `regularUsers` the ability to remove the label `foo` from nodes of all graphs, use: + +[source, cypher, role=noplay] +---- +DENY REMOVE LABEL foo ON GRAPH * TO regularUsers +---- + +[NOTE] +==== +If a label does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-writes-set-property]] +== The `SET PROPERTY` privilege + +The `SET PROPERTY` privilege allows a user to set a property on a node or relationship element in a graph by using the link:{neo4j-docs-base-uri}/cypher-manual/5/clauses/set/#set-set-a-property[Cypher `SET` clause]: + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] SET PROPERTY "{" { * | property[, ...] } "}" + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + ] + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to `SET` any property on all elements of the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT SET PROPERTY {*} ON HOME GRAPH ELEMENTS * TO regularUsers +---- + +The `SET PROPERTY` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] SET PROPERTY "{" { * | property[, ...] } "}" + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + ] + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to `SET` the property `foo` on nodes with the label `bar` on all graphs, use: + +[source, cypher, role=noplay] +---- +DENY SET PROPERTY { foo } ON GRAPH * NODES bar TO regularUsers +---- + +[NOTE] +==== +If the user attempts to set a property with a property name that does not already exist on the database, the user must also possess the xref:authentication-authorization/database-administration.adoc#access-control-database-administration-tokens[`CREATE NEW PROPERTY NAME`] privilege. +==== + +[NOTE] +==== +If a label, a relationship type, or a property name does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-writes-merge]] +== The `MERGE` privilege + +The `MERGE` privilege is a compound privilege that combines `TRAVERSE` and `READ` (i.e. `MATCH`) with `CREATE` and `SET PROPERTY`. +This is intended to enable the use of the link:{neo4j-docs-base-uri}/cypher-manual/5/clauses/merge/[Cypher `MERGE` command], but it is also applicable to all reads and writes that require these privileges. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] MERGE "{" { * | property[, ...] } "}" + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + ] + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to `MERGE` on all elements of the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT MERGE {*} ON GRAPH neo4j ELEMENTS * TO regularUsers +---- + +It is not possible to deny the `MERGE` privilege. +If you wish to prevent a user from creating elements and setting properties: use xref:authentication-authorization/privileges-writes.adoc#access-control-privileges-writes-create[`DENY CREATE`] or xref:authentication-authorization/privileges-writes.adoc#access-control-privileges-writes-set-property[`DENY SET PROPERTY`]. + +[NOTE] +==== +If the user attempts to create nodes with a label that does not already exist on the database, the user must also possess the +xref:authentication-authorization/database-administration.adoc#access-control-database-administration-tokens[`CREATE NEW LABEL`] privilege. +The same applies to new relationships and properties - the +xref:authentication-authorization/database-administration.adoc#access-control-database-administration-tokens[`CREATE NEW RELATIONSHIP TYPE`] or +xref:authentication-authorization/database-administration.adoc#access-control-database-administration-tokens[`CREATE NEW PROPERTY NAME`] privileges are required. +==== + +[NOTE] +==== +If a label, a relationship type, or a property name does not exist in the database, the user cannot use the corresponding privilege until it is created. +See xref:authentication-authorization/limitations.adoc#access-control-limitations-non-existing-labels[Privileges for non-existing labels, relationship types, and property names] for more information. +==== + + +[[access-control-privileges-writes-write]] +== The `WRITE` privilege + +The `WRITE` privilege allows the user to execute any `WRITE` command on a graph. + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] WRITE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to grant the role `regularUsers` the ability to `WRITE` on the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT WRITE ON GRAPH neo4j TO regularUsers +---- + +[NOTE] +==== +Unlike the more specific `WRITE` commands, it is not possible to restrict `WRITE` privileges to specific +ELEMENTS+, +NODES+ or +RELATIONSHIPS+. +If you wish to prevent a user from writing to a subset of database objects, a `GRANT WRITE` can be combined with more specific `DENY` commands to target these elements. +==== + +The `WRITE` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] WRITE + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to deny the role `regularUsers` the ability to `WRITE` on the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +DENY WRITE ON GRAPH neo4j TO regularUsers +---- + +[NOTE] +==== +Users with `WRITE` privilege but restricted `TRAVERSE` privileges will not be able to do `DETACH DELETE` in all cases. +See xref:tutorial/access-control#detach-delete-restricted-user[delete restricted user] for more info. +==== + + +[[access-control-privileges-writes-all]] +== The `ALL GRAPH PRIVILEGES` privilege + +The `ALL GRAPH PRIVILEGES` privilege allows the user to execute any command on a graph: + +[source, syntax, role="noheader"] +---- +GRANT [IMMUTABLE] ALL [ [ GRAPH ] PRIVILEGES ] + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to grant the role `regularUsers` `ALL GRAPH PRIVILEGES` on the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +GRANT ALL GRAPH PRIVILEGES ON GRAPH neo4j TO regularUsers +---- + +[NOTE] +==== +Unlike the more specific `READ` and `WRITE` commands, it is not possible to restrict `ALL GRAPH PRIVILEGES` to specific +ELEMENTS, +NODES+ or +RELATIONSHIPS+. +If you wish to prevent a user from reading or writing to a subset of database objects, a `GRANT ALL GRAPH PRIVILEGES` can be combined with more specific `DENY` commands to target these elements. +==== + +[NOTE] +==== +The `ALL GRAPH PRIVILEGES` privilege does not allow creating new labels, relationship types, or property names. +These are instead managed by the `NAME MANAGEMENT` privileges. +==== + +The `ALL GRAPH PRIVILEGES` privilege can also be denied: + +[source, syntax, role="noheader"] +---- +DENY [IMMUTABLE] ALL [ [ GRAPH ] PRIVILEGES ] + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + TO role[, ...] +---- + +For example, to deny the role `regularUsers` all graph privileges on the graph `neo4j`, use: + +[source, cypher, role=noplay] +---- +DENY ALL GRAPH PRIVILEGES ON GRAPH neo4j TO regularUsers +---- diff --git a/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc new file mode 100644 index 000000000..b907845da --- /dev/null +++ b/modules/ROOT/pages/authentication-authorization/property-based-access-control.adoc @@ -0,0 +1,181 @@ +:description: How to use Cypher to manage property-based access control on a graph. + +//// +[source, cypher, role=test-setup] +---- +CREATE ROLE regularUsers; +---- +//// + + +:page-role: enterprise-edition aura-db-business-critical aura-db-dedicated new-5.24 + +[[property-based-access-control]] += Property-based access control + +Property-based access control grants permissions to users to read node properties based on property/value conditions. +Each property-based privilege can only be restricted by a single property. +For information about read privileges and their syntax, see xref:authentication-authorization/privileges-reads.adoc[Read privileges]. + +[IMPORTANT] +==== +When using property-based access control, ensure the property used for the rule cannot be modified. +Users who can change this property can affect the granted property-based privileges. +==== + + +== Syntax + +To specify the property/value conditions of the read privilege, you can use the following syntax: + +[source, syntax, role="noheader"] +---- +{GRANT | DENY | REVOKE [GRANT | DENY]} +[IMMUTABLE] +{MATCH | READ | TRAVERSE} + ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } } + [ + ELEMENT[S] { * | label-or-rel-type[, ...] } + | NODE[S] { * | label[, ...] } + | RELATIONSHIP[S] { * | rel-type[, ...] } + | FOR { + +([var][:label["|" ...]] "{" property: value "}") + | (var[:label["|" ...]]) + WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } + | (var[:label["|" ...]] +WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } ) +} + + {TO | FROM} role[, ...] +---- + + +== Performance considerations + +Adding property-based access control may lead to a significant performance overhead in certain scenarios. +See xref:authentication-authorization/limitations.adoc#property-based-access-control-limitations[Limitations] for more detailed information. + +When having property rules, the following factors can worsen the impact on performance: + +* The number of properties on the nodes concerned (more properties = greater performance impact). +* The number of property-based privileges (more property-based privileges = greater performance impact). +* The type of the privilege: `TRAVERSE` property-based privileges have greater performance impact than `READ` property-based privileges. +* The type of storage medium in operation. The impact of the property-based privileges on performance is considerably amplified by accessing disc storage. + +To reduce the performance impact, it is recommended to use the `block` storage format as it is better optimized for the kind of read required for the resolution of property-based privileges. + +For performance-critical scenarios, it is recommended to design privileges based on labels. + + +== Examples + +You can use the following syntax for defining a property-based privilege: + +[source, syntax, role="noheader"] +---- +GRANT privilege-name ON GRAPH graph-name FOR pattern TO role-name +---- + +[NOTE] +==== +The user role does not need to have `READ` privilege for the property used by the property-based privilege. +==== + +=== Grant a property-based privilege on a specific property using its value + +The following example shows how to grant permission to `READ` the `address` property on `Email` or `Website` nodes with domain `exampledomain.com` to role `regularUsers`: + +[source, syntax, role="noheader"] +---- +GRANT READ { address } ON GRAPH * FOR (n:Email|Website) WHERE n.domain = 'exampledomain.com' TO regularUsers +---- + +Alternatively, you can use the following syntax: + +[source, syntax, role="noheader"] +---- +GRANT READ { address } ON GRAPH * FOR (:Email|Website {domain: 'exampledomain.com'}) TO regularUsers +---- + + +=== Grant a property-based privilege using `NULL` + +The following example shows how to grant permission to `TRAVERSE` nodes with the label `Email` where property `classification` is `NULL` to role `regularUsers`: + +[source, syntax, role="noheader"] +---- +GRANT TRAVERSE ON GRAPH * FOR (n:Email) WHERE n.classification IS NULL TO regularUsers +---- + +=== Deny a property-based privilege using a comparison operator + +The following example shows how to deny permission to `READ` and `TRAVERSE` nodes where the property `classification` is different from `UNCLASSIFIED` to role `regularUsers`: + +[source, syntax, role="noheader"] +---- +DENY MATCH {*} ON GRAPH * FOR (n) WHERE n.classification <> 'UNCLASSIFIED' TO regularUsers +---- + +=== Grant a property-based privilege on all properties using a property value + +The following example shows how to grant permission to `READ` all properties on nodes where the property `securityLevel` is higher than `3` to role `regularUsers`: + +[source, syntax, role="noheader"] +---- +GRANT READ {*} ON GRAPH * FOR (n) WHERE n.securityLevel > 3 TO regularUsers +---- + +[NOTE] +==== +The role `regularUsers` does not need to have `READ` privilege for the property `securityLevel` used by the property-based privilege. +==== + +=== Deny a property-based privilege using a list of values + +The following example shows how to deny permission to `READ` all properties on nodes where the property `classification` is not included in the list of `[UNCLASSIFIED, PUBLIC]`: + +[source, syntax, role="noheader"] +---- +DENY READ {*} ON GRAPH * FOR (n) WHERE NOT n.classification IN ['UNCLASSIFIED', 'PUBLIC'] TO regularUsers +---- + +// The last two examples were added in 5.26. + +[role=label--new-5.26] +=== Grant a property-based privilege using temporal value + +The following example shows how to grant permission to `READ` all properties on nodes where the property `createdAt` is later than the current date: + +[source, syntax, role="noheader"] +---- +GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date() TO regularUsers +---- + +[NOTE] +==== +The `date()` function is evaluated, and the value used to evaluate the privilege is the date when the property-based privilege is created. +Keep this in mind when designing your property rules, and use the `SHOW PRIVILEGES AS COMMANDS` command to check the stored value. +This is essential when revoking property-based privileges containing evaluated function values like `date()`. +==== + +[NOTE] +==== +Not all temporal values are comparable, see link:{neo4j-docs-base-uri}/cypher-manual/current/values-and-types/ordering-equality-comparison[Cypher Manual -> Equality, ordering, and comparison of value types]. +==== + +You can show the privilege created by the command in the previous example as a revoke command by running: + +[source, syntax, role="noheader"] +---- +SHOW ROLE regularUsers PRIVILEGES AS REVOKE COMMANDS +---- + +.Result +[options="header,footer", width="100%", cols="m"] +|=== +|command +|"REVOKE GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date('2024-10-25') FROM `regularUsers`" +a|Rows: 1 +|=== + diff --git a/modules/ROOT/pages/authentication-authorization/sso-integration.adoc b/modules/ROOT/pages/authentication-authorization/sso-integration.adoc index 030870d2e..64956516b 100644 --- a/modules/ROOT/pages/authentication-authorization/sso-integration.adoc +++ b/modules/ROOT/pages/authentication-authorization/sso-integration.adoc @@ -1,11 +1,11 @@ [role=enterprise-edition] [[auth-sso-integration]] -= Integration with Single Sign-On Services += Single sign-on integration :description: This page describes Neo4j support for integrating with SSO identity providers using OpenID Connect. -Neo4j supports OpenID Connect (OIDC), which allows for integration with many identity providers including Okta, Microsoft Azure Active Directory, and Google. -This integration permits federated users, managed by the identity provider, to access Neo4j instead of, or in addition to the native users and roles. -For examples with different providers and troubleshooting, see the xref:tutorial/tutorial-sso-configuration.adoc[SSO configuration tutorial]. +Neo4j supports OpenID Connect (OIDC), which allows for integration with many identity providers including Okta, Microsoft Entra ID, and Google. +This integration permits federated users, managed by the identity provider, to access Neo4j instead of, or in addition to the native users and roles. +For examples with different providers and troubleshooting, see the xref:tutorial/tutorial-sso-configuration.adoc[SSO configuration tutorial]. [[auth-sso-parameters]] == OIDC configuration settings @@ -15,140 +15,166 @@ In the configuration examples below the provider-specific prefix is represented For example, if you are using Okta as your identity provider you might use `okta` in the place of `` below. The following configuration settings are important to consider when configuring single sign-on. -For a more detailed overview of the single sign-on configuration options, see xref:reference/configuration-settings.adoc[Configuration settings]. -These settings can also be updated while the database is running, see xref:configuration/dynamic-settings.adoc[Dynamic settings] for more information on how to do this. +For a more detailed overview of the single sign-on configuration options, see xref:configuration/configuration-settings.adoc[Configuration settings]. +Some of these settings can also be updated while the database is running, see xref:configuration/dynamic-settings.adoc[Dynamic settings] for more information on how to do this. Altering any of these settings causes users to re-authenticate as their permissions may have changed as a result. -[options="header",cols="<3,<1,<3"] +[options="header",cols="<3,<1,<1,<3"] |=== | Parameter name | Default value +| Dynamic | Description -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.display_name[dbms.security.oidc..display_name] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.display_name[dbms.security.oidc..display_name] | +| false | The display name for the provider. This is displayed in clients such as Neo4j Browser and Bloom. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.auth_flow[dbms.security.oidc..auth_flow] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.auth_flow[dbms.security.oidc..auth_flow] | pkce +| true | The OIDC auth_flow for clients such as Neo4j Browser and Bloom to use. Supported values are `pkce` and `implicit`. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.well_known_discovery_uri[dbms.security.oidc..well_known_discovery_uri] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.well_known_discovery_uri[dbms.security.oidc..well_known_discovery_uri] | +| true | The OpenID Connect Discovery URL for the provider. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.auth_endpoint[dbms.security.oidc..auth_endpoint] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.auth_endpoint[dbms.security.oidc..auth_endpoint] | +| true | URL of the provider's Authorization Endpoint. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.auth_params[dbms.security.oidc..auth_params] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.auth_params[dbms.security.oidc..auth_params] | +| true | Optional parameters that clients may require with the Authorization Endpoint. The map is a semicolon-separated list of key-value pairs. For example: k1=v1;k2=v2. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.token_endpoint[dbms.security.oidc..token_endpoint] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.token_endpoint[dbms.security.oidc..token_endpoint] | +| true | URL of the provider's OAuth 2.0 Token Endpoint. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.token_params[dbms.security.oidc..token_params] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.token_params[dbms.security.oidc..token_params] | +| true | Option parameters that clients may require with the Token Endpoint. The map is a semicolon-separated list of key-value pairs. For example: k1=v1;k2=v2. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.jwks_uri[dbms.security.oidc..jwks_uri] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.jwks_uri[dbms.security.oidc..jwks_uri] | +| true | URL of the provider's JSON Web Key Set. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.user_info_uri[dbms.security.oidc..user_info_uri] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.user_info_uri[dbms.security.oidc..user_info_uri] | +| true | URL of the provider's UserInfo Endpoint. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.issuer[dbms.security.oidc..issuer] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.issuer[dbms.security.oidc..issuer] | +| true | URL that the provider asserts as its issuer identifier. This will be checked against the `iss` claim in the token. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.audience[dbms.security.oidc..audience] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.audience[dbms.security.oidc..audience] | +| true | The expected value for the `aud` claim. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.client_id[dbms.security.oidc..client_id] -| -| The `client_id` of this client as issued by the provider. - -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.params[dbms.security.oidc..params] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.params[dbms.security.oidc..params] | +| true | Option parameters that clients may require. The map is a semicolon-separated list of key-value pairs. For example: k1=v1;k2=v2. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.config[dbms.security.oidc..config] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.config[dbms.security.oidc..config] | +| true | Option additional configuration that clients may require. The map is a semicolon-separated list of key-value pairs. For example: k1=v1;k2=v2. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.get_groups_from_user_info[dbms.security.oidc..get_groups_from_user_info] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.get_groups_from_user_info[dbms.security.oidc..get_groups_from_user_info] | false +| true | Whether to fetch the groups claim from the user info endpoint on the identity provider. The default is `false`, to read the claim from the token. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.get_username_from_user_info[dbms.security.oidc..get_username_from_user_info] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.get_username_from_user_info[dbms.security.oidc..get_username_from_user_info] | false +| true | Whether to fetch the username claim from the user info endpoint on the identity provider. The default is `false`, to read the claim from the token. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.claims.username[dbms.security.oidc..claims.username] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.claims.username[dbms.security.oidc..claims.username] | sub -| The claim to use for the database username. +| true +| The claim to use for the database username. Neo4j expects to find a string claim in the JWT or user_info response with this name. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.claims.groups[dbms.security.oidc..claims.groups] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.claims.groups[dbms.security.oidc..claims.groups] | -| The claim to use for the database roles. +| true +| The claim to use for the database roles. Neo4j expects to find a claim in the JWT or user_info response with this name. The claim may be a string claim representing a single role or a string array claim representing multiple roles. From Neo4j 5.4, the JWT claim may also contain a single group returned as a string as well as a list of groups as was previously required. -| xref:reference/configuration-settings.adoc#config_dbms.security.oidc.-provider-.authorization.group_to_role_mapping[dbms.security.oidc..authorization.group_to_role_mapping] +| xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.authorization.group_to_role_mapping[dbms.security.oidc..authorization.group_to_role_mapping] | +| true | List an authorization mapping from groups to the pre-defined built-in roles `admin`, `architect`, `publisher`, `editor`, and `reader`, or to any custom-defined roles. + +| xref:configuration/configuration-settings.adoc#config_dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled[dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled] +| false +| false +| When set to `true`, it logs the claims from the JWT into the security log (provided the security log level is also set to `DEBUG`). |=== [[auth-sso-configure-sso]] == Configure Neo4j to use OpenID Connect -First, you configure Neo4j to use OpenID Connect as an authentication and authorization provider. +First, you configure Neo4j to use OpenID Connect as an authentication and authorization provider in the _neo4j.conf_ file. -. Uncomment the setting `dbms.security.auth_enabled=false` and change its value to `true` to enable the security feature. +. Make sure security is turned on. +The default value for `dbms.security.auth_enabled` is `true`. . Uncomment the settings `dbms.security.authentication_providers` and `dbms.security.authorization_providers` and change their value to `oidc-`, where `` maps to the provider name used in the configuration settings. This way, the OIDC connector is used as a security provider for both authentication and authorization. -These configuration values are comma-separated lists, so if you wish to continue to use native authentication and authorization alongside SSO, then these providers can be added to the existing `native` provider: +If you want, you can still use the `native` provider for mixed-mode authentication and authorization. +The values are comma-separated and queried in the declared order. + -.Configuration +.Configure Neo4j to use two OpenID Connect and the native authentication and authorization providers. ====== [source,configuration,role="noheader"] ---- dbms.security.authentication_providers=oidc-newsso,oidc-oldsso,native dbms.security.authorization_providers=oidc-newsso,oidc-oldsso,native ---- -This example has two OpenID Connect providers configured, as well as Neo4j native authorization and authentication. ====== +. Check connectivity. +Neo4j needs to connect to the identity provider to discover settings and fetch public keys to verify tokens. +Check firewall settings and security controls, and, if necessary, logs to ensure that the Neo4j server is able to connect to the identity provider using HTTPS. +If a proxy is required, this can be link:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/doc-files/net-properties.html#Proxies[configured] in the Java virtual machine using the configuration setting xref:configuration/configuration-settings.adoc#config_server.jvm.additional[server.jvm.additional]. +Proxies that require credentials are not supported. [[auth-sso-map-idp-roles]] -== Map the Identity Provider Groups to the Neo4j Roles +== Map the identity provider groups to the Neo4j roles Before identity provider managed groups can be used with Neo4j, you have to decide on an approach for mapping identity provider groups to Neo4j roles. The simplest approach is to create identity provider groups with the same names as Neo4j roles. If you decide to go this way, no mapping configuration is necessary. Assuming, however, that identity provider groups do not directly map 1:1 to the desired Neo4j roles, it is necessary to map the identity provider groups to the xref:authentication-authorization/built-in-roles.adoc[Neo4j built-in] and custom-defined roles. To do that, you need to know what privileges the Neo4j roles have, and based on these privileges, create the mapping to the groups defined in the identity provider. -The map must be formatted as a semicolon-separated list of key-value pairs, where the key is a comma-separated list of the identity provider group names and the value is a comma-separated list of the corresponding role names. -For example, `group1=role1;group2=role2;group3=role3,role4,role5;group4,group5=role6`. +The map must be formatted as a semicolon-separated list of key-value pairs, where the key is the identity provider group name and the value is a comma-separated list of the corresponding role names. +For example, `group1=role1;group2=role2;group3=role3,role4,role5;group4=role6;group5=role6`. .Example of identity provider groups to Neo4j roles mapping ==== [source, role=noheader] ---- dbms.security.oidc.mysso.authorization.group_to_role_mapping=\ - neo4j_readonly = reader; \ #<1> - neo4j_rw = editor,publisher; \ #<2> - neo4j_rw,neo4j_create = publisher; \ #<3> - neo4j_create,neo4j_schema = architect; \ - neo4j_dba = admin; \ - neo4j_exec = rolename #<4> + neo4j_readonly = reader; \ #<1> + neo4j_rw = editor,publisher; \ #<2> + neo4j_rw = publisher; \ #<3> + neo4j_create = publisher; \ + neo4j_dba = admin; \ + neo4j_exec = rolename #<4> ---- <1> Mapping of an identity provider group to a Neo4j built-in role. @@ -156,23 +182,29 @@ dbms.security.oidc.mysso.authorization.group_to_role_mapping=\ <3> Mapping of two identity provider groups to a Neo4j built-in role. <4> Mapping of an identity provider group to a custom-defined role. Custom-defined roles, such as `rolename`, must be explicitly created using the `CREATE ROLE rolename` command before they can be used to grant privileges. -See link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/access-control/manage-users[the Cypher Manual -> Creating roles]. +See xref:authentication-authorization/manage-roles.adoc[Manage roles]. +==== + +[NOTE] +==== +When specifying explicit group to role mapping the automatic mapping for groups and roles sharing a name is disabled. +This means that all groups and roles need to be specified to be mapped, even if they share a name. ==== [[auth-sso-configure-provider]] -== Configure Neo4j to use an OpenID Connect Identity Provider +== Configure Neo4j to use an OpenID Connect identity provider This option allows users to log in through an OIDC compliant identity provider by offering a token from the provider instead of a username and password. Typically, these tokens take the form of a signed JSON Web Token (JWT). -In the configuration examples below, we are using `mysso` as our provider name. +The following configuration examples use `mysso` as the provider's name. It is recommended to use a name describing the provider that is being integrated. [[auth-sso-configure-provider-jwt]] -=== OpenID Connect Using JWT Claims +=== OpenID Connect using JWT claims In this configuration, Neo4j receives a JWT from the identity provider containing claims representing the database username (e.g. email), and the Neo4j roles. -. Set a Display Name +. Set a display name. + In the _neo4j.conf_ file, uncomment and configure the following settings: + @@ -180,9 +212,9 @@ In the _neo4j.conf_ file, uncomment and configure the following settings: ---- dbms.security.oidc.mysso.display_name=SSO Provider ---- -This is displayed on a button on the login page of clients such as Neo4j Browser and Bloom, so that users can identify the provider they are using to login. +This is displayed on a button on the login page of clients, such as Neo4j Browser and Bloom so that you can identify the provider you are using to login. -. Configure Discovery: +. Configure discovery. + Uncomment and configure the following settings: + @@ -190,7 +222,7 @@ Uncomment and configure the following settings: ---- dbms.security.oidc.mysso.well_known_discovery_uri=https://my-idp.example.com/.well-known/openid-configuration ---- -The `well_known_discovery` endpoint of the identity provider supplies the OpenID Provider Metadata to allow Neo4j to interact with a provider. +The `well_known_discovery` endpoint of the identity provider supplies the OpenID provider metadata to allow Neo4j to interact with that provider. It is also possible to configure the provider settings manually: + [source, properties] @@ -203,7 +235,7 @@ dbms.security.oidc.mysso.issuer=abcd1234 ---- Manual settings always take priority over those retrieved from the discovery endpoint. -. Configure Audience: +. Configure audience. + Provide the expected value for the audience(`aud`) claim: + @@ -211,18 +243,11 @@ Provide the expected value for the audience(`aud`) claim: ---- dbms.security.oidc.mysso.claims.audience=myaudience ---- -In some situations there may be multiple values for the `aud` claim. -In this situation, the id_token should contain an authorized party(`azp`) claim containing the client id, which is configured as follows: -+ -[source, properties] ----- -dbms.security.oidc.mysso.claims.client_id=myclientid ----- -. Configure Claims: +. Configure claims. + Provide the name of the claims that map to the database username and roles. -`username` is expected to be a string claim and `roles` is expected to be a list of strings. +`username` is expected to be a string claim, and `roles` is expected to be a list of strings representing a set of roles or a single string representing a single role: + [source, properties] ---- @@ -231,26 +256,136 @@ dbms.security.oidc.mysso.claims.groups=roles ---- . Optionally, map the groups in the OIDC groups claim to the Neo4j built-in and custom roles. -See xref:authentication-authorization/sso-integration.adoc#auth-sso-map-idp-roles[Map the Identity Provider Groups to the Neo4j Roles]. ++ +See <> + [[auth-sso-configure-provider-userinfo]] -=== OpenID Connect Fetching Claims from Provider +=== OpenID Connect fetching claims from a provider -In this configuration, Neo4j receives a token from the identity provider and uses that token to call back to the identity provider using its UserInfo endpoint to retrieve claims for the database username and Neo4j roles. +In this configuration, Neo4j receives a token from the identity provider and uses that token to call back to the identity provider using its _UserInfo_ endpoint to retrieve claims for the database username and Neo4j roles. -. Configure as for JWT Claims. -+ -Configure Neo4j for xref:authentication-authorization/sso-integration.adoc#auth-sso-configure-provider-jwt[OpenID Connect Using JWT Claims]. +. Configure Neo4j for xref:authentication-authorization/sso-integration.adoc#auth-sso-configure-provider-jwt[OpenID Connect Using JWT Claims]. -. Configure the claims to fetch from the UserInfo endpoint: +. Configure the claims to fetch from the _UserInfo_ endpoint: + [source, properties] ---- dbms.security.oidc.mysso.get_username_from_user_info=true dbms.security.oidc.mysso.get_groups_from_user_info=true ---- ++ It is possible to fetch just the username, just the groups, or both from the userinfo endpoint. +[role=label--new-5.24] +[[auth-sso-auth-providers]] +=== Configure SSO at the user level using auth providers +xref:authentication-authorization/auth-providers.adoc[User auth providers] can be used to determine which users can authenticate and authorize using the configured providers. + +You must change the xref:configuration/configuration-settings.adoc#config_dbms.security.require_local_user[`dbms.security.require_local_user`] configuration setting to `true` to use auth providers. +This means that a user with a matching auth provider *must* exist in order to be able to authenticate and authorize. +This applies to all providers. + +Conversely, when xref:configuration/configuration-settings.adoc#config_dbms.security.require_local_user[`dbms.security.require_local_user`] is set to `false`, users' auth providers have no bearing on the way that they are authenticated and authorized, instead authentication and authorization is controlled centrally (for all users) by the database configuration. + +The following examples show how to configure users with auth provider using Cypher. + +.Create a user with an auth provider who can authenticate and authorize using `mysso` +====== +[source,cypher,role=noplay] +---- +CREATE USER jake +SET AUTH 'oidc-mysso' {SET ID 'jakesUniqueMySsoId'} // the id must match the claim that you configured via dbms.security.oidc.mysso.claims.username +---- + +The command creates the user `jake` who can authenticate and authorize using `mysso` provided they present a valid token with a `sub` claim of `jakesUniqueMySsoId`. +The claim used for authentication is determined by the xref:configuration/configuration-settings.adoc#config_dbms.security.oidc.-provider-.claims.username[`dbms.security.oidc.mysso.claims.username`] config setting (the default is the `sub` claim). +====== + + +.Create a user with two auth providers allowing the user to authenticate and authorize with one of them +====== +[source,cypher,role=noplay] +---- +CREATE USER jake +SET HOME DATABASE anotherDb +SET AUTH 'oidc-mysso1' {SET ID 'jakesUniqueMySso1Id'} // `jakesUniqueMySso1Id` must match the value of the claim that you configured via dbms.security.oidc.mysso1.claims.username +SET AUTH 'oidc-mysso2' {SET ID 'jakesUniqueMySso2Id'} // `jakesUniqueMySso2Id` must match the value of the claim that you configured via dbms.security.oidc.mysso2.claims.username +---- +The command creates the user `jake` who can authenticate and authorize using `mysso1` or `mysso2`. +The example also illustrates that the user can have their home database set even when using only external auth providers. +====== + + +.Alter a user to remove one of their auth providers +====== +[source,cypher,role=noplay] +---- +ALTER USER jake +REMOVE AUTH 'oidc-mysso2' +---- +The command prevents the user `jake` from being able to authenticate and authorize with the `mysso2` provider. +====== + +.Alter a user to allow them to authenticate and authorize using username and password +====== +[source,cypher,role=noplay] +---- +ALTER USER jake +SET AUTH 'native' {SET PASSWORD 'changeme' SET PASSWORD CHANGE REQUIRED} +---- +The command allows the user `jake` to authenticate and authorize using the specified username and password (in addition to what they are already configured to use). +====== + + +.Configure the database to allow authentication via `mysso` and authorization via the `native` provider +====== + +. Set the following database config: ++ +[source, properties] +---- +dbms.security.authentication_providers=oidc-mysso +dbms.security.authorization_providers=native +---- + +. Create a user with a `mysso` auth provider: ++ +[source,cypher,role=noplay] +---- +CREATE USER jake +SET AUTH 'oidc-mysso' {SET ID 'jakesUniqueMySsoId'} // `jakesUniqueMySsoId` must match the value of the claim that you configured via dbms.security.oidc.mysso.claims.username +---- + +. Natively grant the `READER` role to the user: ++ +[source,cypher,role=noplay] +---- +GRANT ROLE READER TO jake +---- ++ +The command allows the user `jake` to authenticate using `mysso` and receive the `READER` role from the `native` provider. + +. You can also give the user the union of roles from `mysso` *and* `native` by setting `mysso` as an authorization provider too: ++ +[source, properties] +---- +dbms.security.authentication_providers=oidc-mysso +dbms.security.authorization_providers=native,oidc-mysso +---- +====== + +.Suspend a user +====== +[source,cypher,role=noplay] +---- +ALTER USER jake +SET STATUS SUSPENDED + +---- +The command completely prevents the user from being able to authenticate/authorize by any means. +====== + [[auth-sso-self-signed-certificate]] == Use a self-signed certificate (SSL) in a test environment @@ -267,3 +402,20 @@ server.jvm.additional=-Djavax.net.ssl.keyStorePassword=mypasword server.jvm.additional=-Djavax.net.ssl.trustStore=/path/to/MyCert.jks server.jvm.additional=-Djavax.net.ssl.trustStorePassword=mypasword ---- + +[[auth-sso-debug-jwt-claims]] +== Debug logging of JWT claims + +While setting up an OIDC integration, it is sometimes necessary to perform troubleshooting. +In these cases, it can be useful to view the claims contained in the JWT supplied by the identity provider. + +To enable the logging of these claims at `DEBUG` level in the security log, set xref:configuration/configuration-settings.adoc#config_dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled[dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled] to be `true` and the security log level to `DEBUG`. +You can do this in _/conf/server-logs.xml_. + +If you need more information on how to set up and manage the security log, see xref:monitoring/logging.adoc#security-events-logging[Configure the security log]. + +[WARNING] +==== +Make sure to set xref:configuration/configuration-settings.adoc#config_dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled[dbms.security.logs.oidc.jwt_claims_at_debug_level_enabled] back to `false` for production environments to avoid unwanted logging of potentially sensitive information. +Also, bear in mind that the set of claims provided by an identity provider in the JWT can change over time. +==== diff --git a/modules/ROOT/pages/authentication-authorization/terminology.adoc b/modules/ROOT/pages/authentication-authorization/terminology.adoc deleted file mode 100644 index ce413efcf..000000000 --- a/modules/ROOT/pages/authentication-authorization/terminology.adoc +++ /dev/null @@ -1,33 +0,0 @@ -[role=enterprise-edition] -[[auth-terminology]] -= Terminology -:description: This page lists the relevant terminology related to authentication and authorization in Neo4j. - -The following terms are relevant to role-based access control within Neo4j: - -[.compact] -[[term-active-user]]active user:: -A user who is active within the system and can perform actions prescribed by any assigned roles on the data. -This is in contrast to a suspended user. - -[[term-administrator]]administrator:: -This is a user who has been assigned the admin role. - -[[term-current-user]]current user:: -This is the currently logged-in user invoking the commands described in this chapter. - -[[term-password-policy]]password policy:: -The password policy is a set of rules of what makes up a valid password. -For Neo4j, the following rules apply: -* The password cannot be the empty string. -* When changing passwords, the new password cannot be the same as the previous password. - -[[term-role]]role:: -This is a collection of actions -- such as read and write -- permitted on the data. - -[[term-suspended-user]]suspended user:: -A user who has been suspended is not able to access the database in any capacity, regardless of any assigned roles. - -[[term-user]]user:: -* A user is composed of a username and credentials, where the latter is a unit of information, such as a password, verifying the identity of a user. -* A user may represent a human, an application etc. diff --git a/modules/ROOT/pages/backup-restore/aggregate.adoc b/modules/ROOT/pages/backup-restore/aggregate.adoc index d9af262f0..53a9575da 100644 --- a/modules/ROOT/pages/backup-restore/aggregate.adoc +++ b/modules/ROOT/pages/backup-restore/aggregate.adoc @@ -1,12 +1,12 @@ [role=enterprise-edition] [[aggregate-backup]] = Aggregate a database backup chain -:description: This section describes how to aggregate a backup chain into a single backup. +:description: This section describes how to aggregate a backup chain into a single backup. [[aggregate-backup-command]] == Command -The aggregate command turns a xref:backup-restore/online-backup.adoc#backup-chain[backup chain] into a single xref:backup-restore/online-backup.adoc#backup-artifact[full backup artifact]. +The aggregate command turns a xref:backup-restore/online-backup.adoc#backup-chain[a chain of backup artifacts] into a single xref:backup-restore/online-backup.adoc#backup-artifact[full backup artifact]. image:backup-chain-aggregation.svg[title="Backup chain aggregation",role="middle"] @@ -24,88 +24,174 @@ This operation is called _recovery_ and can be costly. [source,role=noheader] ---- -neo4j-admin database aggregate-backup --from-path= - [--keep-old-backup[=true|false]] - [--parallel-recovery[=true|false]] - [--verbose] - [--expand-commands] - [--additional-config=] - +neo4j-admin database aggregate-backup [-h] [--expand-commands] + [--verbose] [--keep-old-backup[=true|false]] + [--parallel-recovery[=true|false]] + [--additional-config=] --from-path= + [--temp-path=] [] ---- +=== Description + +Aggregates a chain of backup artifacts into a single artifact. + +[[aggregate-backup-command-parameters]] +=== Parameters + +.`neo4j-admin database aggregate-backup` parameters +[options="header", cols="1m,3a"] +|=== +| Parameter +| Description + +|[] +|Name of the database for which to aggregate the artifacts. Can contain * and ? for globbing. +|=== + + [[aggregate-backup-command-options]] === Options -[options="header",cols="m,m,a"] +.`neo4j-admin database aggregate-backup` options +[options="header", cols="5m,6a,4m"] |=== | Option -| Default | Description +| Default -| --from-path +|--additional-config=footnote:[See xref:tools/neo4j-admin/index.adoc#_configuration[Tools -> Configuration] for details.] +|Configuration file with additional configuration. +| + +| --expand-commands +| Allow command expansion in config value evaluation. | -| Directory where the backup artifacts are located. -Directory where the backup artifacts are located, or optionally the path to a specific _.backup file_ forcing `aggregate` to find the backup chain for that specific backup (and guarding against the risk of identifying the wrong backup chain, if more than one exists in a given directory). + +|--from-path= +|Accepts either a path to a single artifact file or a folder containing backup artifacts. + When a file is supplied, the __ parameter should be omitted. -The option to supply a file is only available in Neo4j 5.2 and later. +It is possible to aggregate backup artifacts from AWS S3 buckets, Google Cloud storage buckets, and Azure buckets using the appropriate URI as the path. +| -| --keep-old-backup -| false -| If set to true, the old backup chain is not removed. +|-h, --help +|Show this help message and exit. +| -| --parallel-recovery -| false -| Allow multiple threads to apply pulled transactions to a backup in parallel. -For some databases and workloads this may reduce aggregate times significantly. -[NOTE] -==== -`parallel-recovery` is an experimental option. +|--keep-old-backup[=true\|false] +|If set to true, the old backup chain is not removed. +|false + +|--parallel-recovery[=true\|false] +|Allow multiple threads to apply pulled transactions to a backup in parallel. +For some databases and workloads, this may reduce aggregate times significantly. +Note: this is an EXPERIMENTAL option. Consult Neo4j support before use. -==== -| --verbose -| -| Enable verbose output. +|false -| --expand-commands +|--temp-path= +|label:new[Introduced in 5.24] Provide a path to a temporary empty directory for storing backup files until the command is completed. The files will be deleted once the command is finished. | -| Allow command expansion in config value evaluation. -| --additional-config +|--verbose +|Enable verbose output. | -| Configuration file to provide additional or override the existing configuration settings in the _neo4j.conf_ file. |=== -[[aggregate-backup-command-parameters]] -=== Parameters -[options="header",cols="m,m,a"] -|=== -| Parameter -| Default -| Description -| -| neo4j -| Name of the database for which to aggregate the artifacts. -Can contain `*` and `?` for globbing. +[NOTE] +==== +The `--from-path=` option can also load backup artifacts from AWS S3 buckets (from Neo4j 5.19), Google Cloud storage buckets (from Neo4j 5.21), and Azure buckets (from Neo4j 5.24). +For more information, see <>. +==== + +[NOTE] +==== +Neo4j 5.24 introduces the `--temp-path` option to address potential issues related to disk space when performing backup-related commands, especially when cloud storage is involved. + +If `--temp-path` is not set, a temporary directory is created inside the directory specified by the `--from-path` option. + +If you don't provide the `--from-path` option or if your provided path points to a cloud storage bucket, a temporary folder is created inside the current working directory for Neo4j. +This fallback option can cause issues because the local filesystem (or the partition where Neo4j is installed) may not have enough free disk to accommodate the intermediate computation. + +Therefore, it is strongly recommended to provide a `--temp-path` option. +==== -|=== [[aggregate-backup-example]] == Examples -.An example of how to perform aggregation of a set of backups located in a given folder for the `neo4j` database. +=== Aggregating a backup chain located in a given folder + +The following is an example of how to perform aggregation of a set of backups located in a given folder for the `neo4j` database: + [source,shell] ---- bin/neo4j-admin database aggregate-backup --from-path=/mnt/backups/ neo4j ---- The command first looks inside the `/mnt/backups/` directory for a backup chain for the database `neo4j`. If found, it is then aggregated into a single backup artifact. -.An example of how to perform aggregation of a set of backups identified using a given backup file for the `neo4j` database. +=== Aggregating a backup chain identified using a given backup file + +The following is an example of how to perform aggregation of a set of backups identified using a given backup file for the `neo4j` database: + [source,shell] ---- bin/neo4j-admin database aggregate-backup --from-path=/mnt/backups/neo4j-2022-10-18T13-00-07.backup ---- The command checks the `/mnt/backups/` directory for a backup chain including the file _neo4j-2022-10-18T13-00-07.backup_, for the database `neo4j`. If found, it is then aggregated into a single backup artifact. -This option is only available in Neo4j 5.2 and later. \ No newline at end of file +This option is only available in Neo4j 5.2 and later. + +[[aggregate-backup-cloud-storage]] +=== Aggregating a backup chain located in a cloud storage + +The following examples show how to perform aggregation of a set of backups located in a cloud storage. + +[.tabbed-example] +===== +[role=include-with-AWS-S3 label--new-5.19] +====== + +include::partial$/aws-s3-overrides.adoc[] + +include::partial$/aws-s3-credentials.adoc[] + +. Then, use the following command to aggregate the backup chain located in a given folder in your AWS S3 bucket. +The example assumes that you have a backup chain located in the `myBucket/myDirectory` folder identifiable by the file `myBackup.backup`: ++ +[source,shell] +---- +bin/neo4j-admin database aggregate-backup --from-path=s3://myBucket/myDirectory/myBackup.backup mydatabase +---- +====== + +[role=include-with-Google-cloud-storage label--new-5.21] +====== + +include::partial$/gcs-credentials.adoc[] + +. Then, use the following command to aggregate the backup chain located in a given folder in your Google storage bucket. +The example assumes that you have a backup chain located in the `myBucket/myDirectory` folder identifiable by the file `myBackup.backup`: ++ +[source,shell] +---- +bin/neo4j-admin database aggregate-backup --from-path=gs://myBucket/myDirectory/myBackup.backup mydatabase +---- +====== + +[role=include-with-Azure-cloud-storage label--new-5.24] +====== + +include::partial$/azb-credentials.adoc[] + +. Then, use the following command to aggregate the backup chain located in a given folder in your Azure blob storage container. +The example assumes that you have a backup chain located with a `myStorageAccount/myContainer/myDirectory` folder identifiable by the file `myBackup.backup`: ++ +[source,shell] +---- +bin/neo4j-admin database aggregate-backup --from-path=azb://myStorageAccount/myContainer/myDirectory/myBackup.backup mydatabase +---- +====== +===== diff --git a/modules/ROOT/pages/backup-restore/copy-database.adoc b/modules/ROOT/pages/backup-restore/copy-database.adoc index 12abdf4d5..f9382a5da 100644 --- a/modules/ROOT/pages/backup-restore/copy-database.adoc +++ b/modules/ROOT/pages/backup-restore/copy-database.adoc @@ -3,49 +3,18 @@ [[copy-database]] = Copy a database store -A user database or backup can be copied to a Neo4j instance using the `copy` command of `neo4j-admin`. +You can use the `neo4j-admin database copy` command to copy a database, create a compacted/defragmented copy of a database, clean up database inconsistencies, or do a direct migration from Neo4j 4.4 to any 5.x version. +`neo4j-admin database copy` reclaims the unused space, creates a defragmented copy of the _data store_, and creates the node label and relationship type lookup indexes. +.Command limitations [NOTE] ==== -`neo4j-admin database copy` is not supported for use on the `system` database. -==== - -[NOTE] -==== -`neo4j-admin database copy` is not supported for use on xref:composite-databases/introduction.adoc#composite-databases-concepts[composite databases]. -It must be run directly on the databases that are part of a composite database. -==== - - -[WARNING] -==== -It is important to note that `neo4j-admin database copy` is an IOPS-intensive process. -Using this process for upgrading or migration purposes can have significant performance implications, depending on your disc specification. -It is therefore not appropriate for all use cases. - - -Estimating the processing time:: -+ --- -Estimations for how long the `neo4j-admin database copy` command takes can be made based upon the following: - -* Neo4j, like many other databases, do IO in 8K pages. -* Your disc manufacturer will have a value for the maximum IOPS it can process. - -For example, if your disc manufacturer has provided a maximum of 5000 IOPS, you can reasonably expect up to 5000 such page operations a second. -Therefore, the maximal theoretical throughput you can expect is 40MB/s (or 144 GB/hour) on that disc. -You may then assume that the best-case scenario for running `neo4j-admin database copy` on that 5000 IOPS disc is that it takes at least 1 hour to process a 144 GB database. footnote:[The calculations are based on `MB/s = (IOPS * B) ÷ 10^6`, -where `B` is the block size in bytes; in the case of Neo4j, this is `8000`. GB/hour can then be calculated from `(MB/s * 3600) ÷ 1000`.] - -However, it is important to remember that the process must read 144 GB from the source database, and must also write to the target store (assuming the target store is of comparable size). -Additionally, there are internal processes during the copy that reads/modifies/writes the store multiple times. -Therefore, with an additional 144 GB of both read and write, the best-case scenario for running `neo4j-admin database copy` on a 5000 IOPS disc is that it takes *at least 3 hours to process a 144 GB database*. - -Finally, it is also important to consider that in almost all Cloud environments, the published IOPS value may not be the same as the actual value, or be able to continuously maintain the maximum possible IOPS. -The real processing time for this example _could_ be well above that estimation of 3 hours. --- - -For detailed information about supported methods of upgrade and migration, see the https://neo4j.com/docs/upgrade-migration-guide/current/[Neo4j Upgrade and Migration Guide]. +* `neo4j-admin database copy` preserves the node IDs (unless `--compact-node-store` is used), but the relationships get new IDs. +* `neo4j-admin database copy` is not supported for use on the `system` database. +* `neo4j-admin database copy` is not supported for use on xref:database-administration/composite-databases/concepts.adoc[Composite databases]. +It must be run directly on the databases that are associated with that Composite database. +* `neo4j-admin database copy` is an IOPS-intensive process. +For more information, see <>. ==== [[copy-database-command]] @@ -53,202 +22,228 @@ For detailed information about supported methods of upgrade and migration, see t `neo4j-admin database copy` copies the _data store_ of an existing **offline** database to a new database. -[[copy-database-usage]] -=== Usage - -The `neo4j-admin database copy` command can be used to clean up database inconsistencies, compact stores, and do a direct migration from Neo4j 3.5 to any 4.x version. -It can process an optional set of filters, which you can use to remove any unwanted data before copying the database. -The command also reclaims the unused space of a database and creates a defragmented copy of that database or backup in the destination Neo4j instance. - -[NOTE] -==== -`neo4j-admin database copy` copies the _data store_ and creates the node label and relationship type lookup indexes. -Any additional _schema_ (indexes and constraints) defined are not included. -However, the command will output Cypher statements, which you can run to recreate the indexes and constraints. -==== - -[TIP] -==== -For a detailed example of how to reclaim unused space, see xref:performance/space-reuse.adoc#space-reuse-reclaim-space[Reclaim unused space]. -// TODO is there a corresponding example that should be linked in the 5.0 docs? -// For a detailed example of how to back up a 3.5 database and use the `neo4j-admin database copy` command to compact its store and migrate it to a 4.x Neo4j standalone instance, see link:{neo4j-docs-base-uri}/upgrade-migration-guide/migration/migrate-to-4.any/online-backup-copy-database/[Upgrade and Migration Guide -> Tutorial: Back up and copy a database in a standalone instance]. -==== - -[WARNING] -==== -`neo4j-admin database copy` preserves the node IDs; however, the relationships get new IDs. -==== - [[copy-database-syntax]] === Syntax [source,role=noheader] ---- -neo4j-admin database copy [--verbose] - [--from-path-data= --from-path-txn=] - [--to-path-data= --to-path-txn=] - [--to-path-schema=] - [--force] - [--compact-node-store[=true|false]] - [--to-format=] - [--ignore-nodes-with-labels=