diff --git a/README.rst b/README.rst index b01d238..83084ec 100644 --- a/README.rst +++ b/README.rst @@ -179,6 +179,17 @@ Alternatively, you can skip the admin console by using a CMS management command: .. |coursegraph admin success| image:: https://user-images.githubusercontent.com/3628148/153107016-fc6354d8-1c61-4728-b0a4-59150a3bf7b2.png :alt: CourseGraph dump page in CMS admin console, showing message after course dumps are successfully enqueued + +Managing Ingress Access +*********************** + +By default, CourseGraph's Neo4j service is accessible to the outside world for HTTP and Bolt traffic via Caddy, the proxy provided by Tutor. Neo4j's bfasic authentication scheme (described in `Managing Users`_) may or may not be sufficient for your security needs. If it is *not* sufficient, then you have two options: + +1. Use your own Web proxy in place of Tutor's Caddy service by setting ``ENABLE_WEB_PROXY=false``. Via your Web proxy, restrict ingress CourseGraph access as desired. If you're not already using your own Web proxy, then this is probably *not* what you want to do, as it'd affect your entire Tutor deployment just for the sake of this plugin. +2. Set ``COURSEGRAPH_RUN_NEO4J=false`` and self-manage a separate Neo4j service, whose ingress access you could control as desired. Then, configure this plugin to point at your self-managed Neo4j service so that CMS can dump to content to it. See the `Configuration`_ section for specifics. If you choose to go this route, the authors of this plugin recommend the `official Neo4j docker image`_ as a starting point for self-hosting Neo4j. + +.. _official Neo4j docker image: https://neo4j.com/developer/docker-run-neo4j/ + .. _Managing Users: Managing Users @@ -191,7 +202,7 @@ This plugin currently ships with Neo4j 3.5 Community Edition, which provides som * ``CALL dbms.security.deleteUser()`` * ``CALL dbms.security.listUsers()`` -Since authorization control is not availble in the Neo4j Community Edition, all users will have full administrative control over Neo4j data, including ability to to read all graphs, modify nodes, modify relationships, and create new users. Because of this, access to any set of CourseGraph Neo4j credentials confers read access to your entire course catalog, as well as the ability to insert fake data into CourseGraph. As such, if your CourseGraph instance is accessible by the public, then **all Neo4j credential sets should be treated as secrets**. +Since authorization control is not availble in the Neo4j Community Edition, all users will have full administrative control over Neo4j data, including ability to to read all graphs, modify nodes, modify relationships, and create new users. Because of this, access to any set of CourseGraph Neo4j credentials confers read access to your entire course catalog, as well as the ability to insert fake data into CourseGraph. As such, if your CourseGraph instance is accessible by the public, then **all Neo4j credential sets should be treated as production secrets**. By default, this plugin initializes Neo4j with one user, whose username is ``neo4j`` and whose password is set from the ``COURSEGRAPH_NEO4J_PASSWORD`` Tutor setting. When CMS pushes data to Neo4j, it also authenticates with ``neo4j`` as its username and ``COURSEGRAPH_NEO4J_PASSWORD`` as its password. Keep in mind that: @@ -203,6 +214,8 @@ Finally, initializing CourseGraph with ``COURSEGRAPH_NEO4J_PASSWORD`` set to ``! .. _Procedures for native user management: https://neo4j.com/docs/operations-manual/3.5/authentication-authorization/native-user-role-management/procedures/ +.. _Configuration: + Configuration ************* @@ -235,6 +248,10 @@ The Tutor plugin can be configured with several settings. The names of all setti - bool - ``true`` - Should CMS automatically dump a course to CourseGraph whenever it's published? If disabled, you will instead need to periodically dump courses via the management command or admin console. + * - ``RUN_NEO4J`` + - bool + - ``true`` + - Whether the Neo4j service should be started. Only disable if you wish to manage your own Neo4j instance outside of Tutor. If you disable this, then set ``COURSEGRAPH_NEO4J_HOST`` to the hostname of your self-managed instance, set ``COURSEGRAPH_NEO4J_PASSWORD`` to the password of your instance's ``neo4j`` user, and expose port 7687 for unencrypted Bolt traffic. Development diff --git a/tutorcoursegraph/__about__.py b/tutorcoursegraph/__about__.py index 20c358e..e48bc28 100644 --- a/tutorcoursegraph/__about__.py +++ b/tutorcoursegraph/__about__.py @@ -2,4 +2,4 @@ Expose some package metadata. """ -__version__ = "14.0.0rc3" +__version__ = "14.0.0rc4" diff --git a/tutorcoursegraph/patches/caddyfile b/tutorcoursegraph/patches/caddyfile index c0ae48e..dcf223f 100644 --- a/tutorcoursegraph/patches/caddyfile +++ b/tutorcoursegraph/patches/caddyfile @@ -1,3 +1,4 @@ +{% if COURSEGRAPH_RUN_NEO4J %} # CourseGraph Web frontend. {{ COURSEGRAPH_NEO4J_HOST }}{$default_site_port} { @@ -31,3 +32,5 @@ bolt.{{ COURSEGRAPH_NEO4J_HOST }}{$default_site_port} { import proxy "coursegraph:7687" } + +{% endif %} diff --git a/tutorcoursegraph/patches/k8s-deployments b/tutorcoursegraph/patches/k8s-deployments index cfaa335..4456cbc 100644 --- a/tutorcoursegraph/patches/k8s-deployments +++ b/tutorcoursegraph/patches/k8s-deployments @@ -1,3 +1,4 @@ +{% if COURSEGRAPH_RUN_NEO4J %} --- apiVersion: apps/v1 kind: Deployment @@ -36,3 +37,4 @@ spec: - name: data persistentVolumeClaim: claimName: coursegraph +{% endif %} diff --git a/tutorcoursegraph/patches/k8s-services b/tutorcoursegraph/patches/k8s-services index d0bf637..48f44cc 100644 --- a/tutorcoursegraph/patches/k8s-services +++ b/tutorcoursegraph/patches/k8s-services @@ -1,3 +1,4 @@ +{% if COURSEGRAPH_RUN_NEO4J %} --- apiVersion: v1 kind: Service @@ -14,3 +15,4 @@ spec: protocol: TCP selector: app.kubernetes.io/name: coursegraph +{% endif %} diff --git a/tutorcoursegraph/patches/k8s-volumes b/tutorcoursegraph/patches/k8s-volumes index b246c07..db9faf1 100644 --- a/tutorcoursegraph/patches/k8s-volumes +++ b/tutorcoursegraph/patches/k8s-volumes @@ -1,3 +1,4 @@ +{% if COURSEGRAPH_RUN_NEO4J %} --- apiVersion: v1 kind: PersistentVolumeClaim @@ -12,3 +13,4 @@ spec: resources: requests: storage: 5Gi +{% endif %} diff --git a/tutorcoursegraph/patches/local-docker-compose-caddy-aliases b/tutorcoursegraph/patches/local-docker-compose-caddy-aliases index 2ba987c..617f346 100644 --- a/tutorcoursegraph/patches/local-docker-compose-caddy-aliases +++ b/tutorcoursegraph/patches/local-docker-compose-caddy-aliases @@ -1,2 +1,4 @@ +{% if COURSEGRAPH_RUN_NEO4J %} - {{ COURSEGRAPH_NEO4J_HOST }} - bolt.{{ COURSEGRAPH_NEO4J_HOST }} +{% endif %} diff --git a/tutorcoursegraph/patches/local-docker-compose-dev-services b/tutorcoursegraph/patches/local-docker-compose-dev-services index e6d6b9c..3e94e21 100644 --- a/tutorcoursegraph/patches/local-docker-compose-dev-services +++ b/tutorcoursegraph/patches/local-docker-compose-dev-services @@ -1,3 +1,4 @@ +{% if COURSEGRAPH_RUN_NEO4J %} coursegraph: ports: - "7474:7474" # Expose Web interface to host. @@ -8,3 +9,4 @@ coursegraph: - "{{ COURSEGRAPH_NEO4J_HOST }}" tty: true # Allow TTY-enabled shell on service with `tutor dev exec coursegraph bash`. stdin_open: true # Allow attachment to service with `docker-compose attach`. +{% endif %} diff --git a/tutorcoursegraph/patches/local-docker-compose-services b/tutorcoursegraph/patches/local-docker-compose-services index fdf0475..bbf720b 100644 --- a/tutorcoursegraph/patches/local-docker-compose-services +++ b/tutorcoursegraph/patches/local-docker-compose-services @@ -1,3 +1,4 @@ +{% if COURSEGRAPH_RUN_NEO4J %} coursegraph: image: "{{ COURSEGRAPH_NEO4J_DOCKER_IMAGE }}" environment: @@ -9,3 +10,4 @@ coursegraph: restart: unless-stopped volumes: - ../../data/coursegraph:/data +{% endif %} diff --git a/tutorcoursegraph/patches/openedx-cms-common-settings b/tutorcoursegraph/patches/openedx-cms-common-settings index 8ec62a3..6dc0c7f 100644 --- a/tutorcoursegraph/patches/openedx-cms-common-settings +++ b/tutorcoursegraph/patches/openedx-cms-common-settings @@ -4,13 +4,16 @@ COURSEGRAPH_DUMP_COURSE_ON_PUBLISH = {{ COURSEGRAPH_DUMP_COURSE_ON_PUBLISH }} COURSEGRAPH_CONNECTION = { "protocol": "bolt", # Plugin only supports Bolt currently. "secure": False, # Connection from CMS to Neo4j will not be encrypted. - "host": "coursegraph", # This works as a K8s-cluster-local or Docker-network-local hostname. "user": "neo4j", # Default Neo4j db user with full write access. "port": 7687, # Canonical port for Bolt traffic. - + {% if COURSEGRAPH_RUN_NEO4J %} + "host": "coursegraph", # This works as a K8s-cluster-local or Docker-network-local hostname. + {% else %} + "host": "{{ COURSEGRAPH_NEO4J_HOST }}", # Hostname of external Neo4j instance. + {% endif %} {% if COURSEGRAPH_NEO4J_PASSWORD %} "password": "{{ COURSEGRAPH_NEO4J_PASSWORD }}", {% else %} - "password": None, + "password": None, # Neo4j authentication disabled. {% endif %} } diff --git a/tutorcoursegraph/plugin.py b/tutorcoursegraph/plugin.py index 4860ecc..62e6e71 100644 --- a/tutorcoursegraph/plugin.py +++ b/tutorcoursegraph/plugin.py @@ -24,6 +24,7 @@ "NEO4J_DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}neo4j:{{ COURSEGRAPH_NEO4J_VERSION }}", "NEO4J_HOST": "coursegraph.{{ LMS_HOST }}", "DUMP_COURSE_ON_PUBLISH": True, + "RUN_NEO4J": True, }, }