Skip to content

Commit

Permalink
feat: introduce COURSGRAPH_RUN_NEO4J setting
Browse files Browse the repository at this point in the history
Allows plugin users to disable the Neo4j service
so that they can self-host it instead, while still
being able to use the aspect of tutor-contrib-coursegraph
which configures CMS to dump course content.

The use-case here is that some users may be
dissatisfied with Neo4j's basic authentication
and would rather host restrict ingress Neo4j traffic
to, for example, an internal employees-only network.

bump version to 14.0.0rc4
  • Loading branch information
kdmccormick committed Mar 29, 2022
1 parent f591d4b commit a885f69
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 5 deletions.
19 changes: 18 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -191,7 +202,7 @@ This plugin currently ships with Neo4j 3.5 Community Edition, which provides som
* ``CALL dbms.security.deleteUser(<username>)``
* ``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:

Expand All @@ -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
*************

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tutorcoursegraph/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Expose some package metadata.
"""

__version__ = "14.0.0rc3"
__version__ = "14.0.0rc4"
3 changes: 3 additions & 0 deletions tutorcoursegraph/patches/caddyfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% if COURSEGRAPH_RUN_NEO4J %}

# CourseGraph Web frontend.
{{ COURSEGRAPH_NEO4J_HOST }}{$default_site_port} {
Expand Down Expand Up @@ -31,3 +32,5 @@ bolt.{{ COURSEGRAPH_NEO4J_HOST }}{$default_site_port} {

import proxy "coursegraph:7687"
}

{% endif %}
2 changes: 2 additions & 0 deletions tutorcoursegraph/patches/k8s-deployments
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% if COURSEGRAPH_RUN_NEO4J %}
---
apiVersion: apps/v1
kind: Deployment
Expand Down Expand Up @@ -36,3 +37,4 @@ spec:
- name: data
persistentVolumeClaim:
claimName: coursegraph
{% endif %}
2 changes: 2 additions & 0 deletions tutorcoursegraph/patches/k8s-services
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% if COURSEGRAPH_RUN_NEO4J %}
---
apiVersion: v1
kind: Service
Expand All @@ -14,3 +15,4 @@ spec:
protocol: TCP
selector:
app.kubernetes.io/name: coursegraph
{% endif %}
2 changes: 2 additions & 0 deletions tutorcoursegraph/patches/k8s-volumes
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% if COURSEGRAPH_RUN_NEO4J %}
---
apiVersion: v1
kind: PersistentVolumeClaim
Expand All @@ -12,3 +13,4 @@ spec:
resources:
requests:
storage: 5Gi
{% endif %}
2 changes: 2 additions & 0 deletions tutorcoursegraph/patches/local-docker-compose-caddy-aliases
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
{% if COURSEGRAPH_RUN_NEO4J %}
- {{ COURSEGRAPH_NEO4J_HOST }}
- bolt.{{ COURSEGRAPH_NEO4J_HOST }}
{% endif %}
2 changes: 2 additions & 0 deletions tutorcoursegraph/patches/local-docker-compose-dev-services
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% if COURSEGRAPH_RUN_NEO4J %}
coursegraph:
ports:
- "7474:7474" # Expose Web interface to host.
Expand All @@ -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 %}
2 changes: 2 additions & 0 deletions tutorcoursegraph/patches/local-docker-compose-services
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% if COURSEGRAPH_RUN_NEO4J %}
coursegraph:
image: "{{ COURSEGRAPH_NEO4J_DOCKER_IMAGE }}"
environment:
Expand All @@ -9,3 +10,4 @@ coursegraph:
restart: unless-stopped
volumes:
- ../../data/coursegraph:/data
{% endif %}
9 changes: 6 additions & 3 deletions tutorcoursegraph/patches/openedx-cms-common-settings
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
}
1 change: 1 addition & 0 deletions tutorcoursegraph/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
}

Expand Down

0 comments on commit a885f69

Please sign in to comment.