Unverified Commit 70c5196f authored by William Tucker's avatar William Tucker Committed by GitHub
Browse files

Merge pull request #228 from ESGF/ansible-auth-config

Added Ansible config for auth components (allowing access control)
parents fc9a1498 0887913a
Loading
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -34,3 +34,55 @@

### See: https://github.com/ESGF/esgf-docker/blob/master/docs/deploy-ansible.md#enabling-ssl


## OPTIONAL: Enabling access control components

#auth_enabled: true/false

## Configuration for the auth service container
#auth_settings:
#  MIDDLEWARE:
#    - authenticate.oauth2.middleware.BearerTokenAuthenticationMiddleware
#    - authenticate.oidc.middleware.OpenIDConnectAuthenticationMiddleware
#    - authorize.opa.middleware.OPAAuthorizationMiddleware
#  OPA_SERVER:
#    package_path: esgf
#    rule_name: allow
#  # Group info keys for authorization
#  OAUTH2_GROUPS_KEY: group_membership
#  OIDC_GROUPS_KEY: group_membership
#  # OAuth Bearer Token auth settings
#  OAUTH_CLIENT_ID:
#  OAUTH_CLIENT_SECRET:
#  OAUTH_TOKEN_URL:
#  OAUTH_TOKEN_INTROSPECT_URL:
#  # OIDC auth settings
#  OIDC_BACKEND_CLIENT_NAME: esgf
#  AUTHLIB_OAUTH_CLIENTS:
#    esgf:
#      client_id:
#      client_secret:
#      authorize_url:
#      userinfo_endpoint:
#      client_kwargs:
#        scope: openid profile email

## Default rego template (override this to use your own).
#opa_policy_template: policy.rego.j2

## Paths to apply the authorisation policy to and the access group that a user will need.
#opa_policy_restricted_paths:
#  - name: threddsdata
#    path: /thredds/fileServer/restricted/.*
#    group: admins
#  - name: example
#    path: /some/restricted/path/.*
#    group: admins

## Your server's name. The default policy will deny requests from other hostnames.
#opa_policy_server_host: example.com

## The logging level of the OPA container. Set this to debug for troubleshooting.
#opa_log_level: info

### See: https://github.com/ESGF/esgf-docker/blob/master/docs/deploy-ansible.md#enabling-access-control
+32 −0
Original line number Diff line number Diff line
@@ -21,6 +21,38 @@ image_pull: true
# Indicates if the auth service should be deployed or not
auth_enabled: false

auth_settings_base:
  MIDDLEWARE:
    - django.middleware.security.SecurityMiddleware
    - django.contrib.sessions.middleware.SessionMiddleware
    - django.middleware.common.CommonMiddleware
    - django.middleware.csrf.CsrfViewMiddleware
    - django.contrib.messages.middleware.MessageMiddleware
    - django.middleware.clickjacking.XFrameOptionsMiddleware
  OPA_SERVER:
    host: opa
    port: 8181
  RESOURCE_URI_QUERY_KEY: rd
  RESOURCE_URI_HEADER_KEY: HTTP_X_ORIGINAL_URL

# Default rego template (override this to use your own)
opa_policy_template: policy.rego.j2

# Paths to apply security restrictions to
opa_policy_restricted_paths: []

# Whitelist access based on the server's hostname
opa_policy_server_host: "{{ ansible_host }}"

# Logging level for the OPA server
opa_log_level: info

# Settings for the opa image
opa_image_prefix: "{{ image_prefix }}"
opa_image_tag: "{{ image_tag }}"
opa_image_pull: "{{ image_pull }}"
opa_image_repository: opa

# Settings for the auth-service image
auth_image_prefix: "{{ image_prefix }}"
auth_image_tag: "{{ image_tag }}"
+49 −1
Original line number Diff line number Diff line
@@ -4,7 +4,47 @@
  docker_network:
    name: esgf

- name: Start auth container
- name: Make auth config directory
  file:
    path: /esg/config/auth
    state: directory

- name: Write rego policy file
  template:
    src: "{{ opa_policy_template }}"
    dest: /esg/config/auth/policy.rego

- name: Write auth service settings
  template:
    src: settings.yaml.j2
    dest: /esg/config/auth/settings.yaml

- name: Start the opa container
  docker_container:
    name: opa
    image: "{{ opa_image_prefix }}/{{ opa_image_repository }}:{{ opa_image_tag }}"
    pull: "{{ opa_image_pull }}"
    detach: yes
    restart_policy: unless-stopped
    exposed_ports:
      - "8181"
    networks:
      - name: esgf
    networks_cli_compatible: yes
    volumes:
      # Mount the policy for the opa server
      - "/esg/config/auth/policy.rego:/policies/policy.rego:ro"
    entrypoint:
      - "/opa"
      - "run"
      - "--ignore=.*"  # exclude hidden dirs created by Kubernetes
      - "--log-level={{ opa_log_level }}"
      - "--server"
      - "/policies"
    state: started
    recreate: yes

- name: Start auth service container
  docker_container:
    name: auth
    image: "{{ auth_image_prefix }}/{{ auth_image_repository }}:{{ auth_image_tag }}"
@@ -15,3 +55,11 @@
      - "8080"
    networks:
      - name: esgf
    networks_cli_compatible: yes
    volumes:
      # Mount the settings for the auth service
      - "/esg/config/auth/settings.yaml:/etc/django/settings.d/20-runtime-settings.yaml:ro"
      # Mount the settings for the auth service
      - "/esg/config/auth/staticfiles:/var/django/staticfiles:ro"
    state: started
    recreate: yes
+6 −1
Original line number Diff line number Diff line
---

- name: Stop auth container
- name: Stop opa container
  docker_container:
    name: opa
    state: absent

- name: Stop auth service container
  docker_container:
    name: auth
    state: absent
+33 −0
Original line number Diff line number Diff line
package esgf

default allow = false

# Determine access to the resource
allow = true {
    allowed_hosts[resource_host]
    count(violation) == 0
}

# Check that the user belongs to a certain group
has_group(name) {
    some i
    input.subject.groups[i] == name
}

# Separate parts of a resource URL, if applicable
parts := regex.find_all_string_submatch_n("^(?:(?:http|https|ftp):\/\/([^\/ ]*))?(\/.*)", input.resource, -1)
resource_host := parts[_][1]
resource_path := parts[_][2]

# Declare all allowed resource hosts
allowed_hosts := {
    "{{ ansible_host }}",
}

# Check requested path against restricted paths
{% for restricted_path in opa_policy_restricted_paths %}
violation["{{ restricted_path['name'] }}"] {
    regex.match("{{ restricted_path['path'] }}", resource_path)
    not has_group("{{ restricted_path['group'] }}")
}
{% endfor %}
 No newline at end of file
Loading