Skip to content
  • There are no suggestions because the search field is empty.

External Access Control

External Access Control is the tenant-level policy for which training assignments a learner must complete before they can carry out a specific action.

An admin decides which assignments are required in the External Access Control settings.

Gating functionality is built into the aspen-connector (SecurityJourney's CI connector), a tool that can be added as a step in GitHub or GitLab CI to wire various Aspen capabilities, as well as external access control, into your pipeline.


How External Access Control Works

Gating functionality runs as a step in your CI pipeline. On each run, it:

  1. Resolves the committer's email from the CI platform.
  2. POST`s{"emails": ["dev@example.com"]}` to Security Journey's external access control status endpoint and reads back the result for that email.
  3. Fails the pipeline with the reason returned if the committer isn't compliant with the External Access Control policy.
  4. Optionally posts that reason as a comment on the pull/merge request, so the committer doesn't have to dig through CI logs to find the reason for the failure.

Note: A failed pipeline does not block a merge by itself. GitHub and GitLab both let a PR/MR merge past a failing check unless you explicitly mark this job as required (see Integration below). Because the check is identity-based rather than code-based, this check is typically used as a merge gate: set it as a required status check (GitHub) or a required pipeline (GitLab) so a non-compliant committer's changes actually can't merge until they complete the outstanding assignments.


Configuration and Setup

Configuring External Access Control

Which assignments are required is configured in Security Journey's admin settings, not in the pipeline. The connector has no input for scoping or overriding this per-repo; it always enforces whatever the tenant has set up.

  1. In your Security Journey tenant admin settings, there is a card called External Access Control.
  2. Under the Required Assignments setting, select every training assignment a learner must complete to satisfy the policy. Only active assignments can be newly selected; if a required assignment is later deactivated or deleted, it stays visible in the list (flagged) so you can catch and clean up stale requirements rather than having it silently drop out.
  3. Selections save immediately.

This tenant-wide list is what Aspen evaluates a learner's training status against, whenever any entrypoint checks compliance (currently only through the aspen-connector).

Prerequisites
  • A Security Journey Aspen API token (ASPEN_API_TOKEN) with the api:aspen_read role. If you're reusing a token provisioned for Adapt/Guardian, confirm it has READ permissions before wiring up gating functionality.

  • Pull/merge request comments (optional, on by default): the pipeline needs write access to post PR/MR comments.

    • GitHub Actions: permissions: pull-requests: write on the job. Note that GitHub forces GITHUB_TOKEN to read-only on pull_request workflows triggered from a fork, regardless of this setting. Commenting will silently skip (with a warning) on fork PRs.
    • GitLab CI: either a project/group access token with the api scope (GITLAB_TOKEN), or CI/CD job token API access enabled for the project Settings → CI/CD → Token Access.
  • No git write access is required for the gate check itself, only for commenting, and only PR/MR comments, never a commit-back.
  • GitLab only: make sure the pipeline's checkout has enough history for the triggering commit to be reachable (GIT_DEPTH: 0 is the safe default). Gating functionality reads the committer's email straight from git log on that commit rather than GitLab's predefined CI/CD variables, which aren't reliable on merge-request pipelines. A shallow clone can leave that lookup with nothing to fall back on but GITLAB_USER_EMAIL (the pipeline-triggering account's email, which may not match the actual commit author).
Integration

Gating functionality integrates via the aspen-connector, same as Adapt and Guardian. Today, this is the connector's CI-side implementation of External Access Control enforcement.

GitHub Actions example:
permissions:

pull-requests: write # needed for gate_comment_on_failure

steps:

- uses: actions/checkout@v4

- uses: SecurityJourney/aspen-connector@v0.2.0

with:

api_token: $

enforce_gate: 'true'

# Optional overrides:

# gate_fail_open: 'true'

# gate_comment_on_failure: 'true'
GitLab CI example:
aspen_gate:

image: node:22

script:

- npx @securityjourney/aspen-connector@0.2.0

variables:

ASPEN_API_TOKEN: $SECURITYJOURNEY_TOKEN

ASPEN_ENFORCE_GATE: 'true'

# Optional overrides:

# ASPEN_GATE_FAIL_OPEN: 'true'

# ASPEN_GATE_COMMENT_ON_FAILURE: 'true'

To block merges on a failed gate, mark this job as a required status check (GitHub branch protection) or require successful pipelines (GitLab merge request settings).


Environment Variables

Variable Required Default Description
ASPEN_API_TOKEN Yes None Security Journey API token
ASPEN_ENFORCE_GATE Yes False Set `true` to run the gate check
ASPEN_GATE_FAIL_OPEN No True If `false`, blocks CI when the gate endpoint reports an internal error, times out, or returns something unreadable. This only covers our own infrastructure failing to answer. It never overrides an actual non-compliant result. See below.
ASPEN_GATE_COMMENT_ON_FAILURE No True Posts the gate failure reason as a comment on the PR/MR when the committer is non-compliant

How a Commit Is Evaluated

Gating functionality looks up the committer's compliance status and evaluates the result matching their email (falling back to the first result if no exact match is found). If Security Journey reports a reason for non-compliance, that's used verbatim; otherwise, the connector builds a fallback reason from the required assignments the committer hasn't completed. If the committer isn't compliant, the pipeline fails with that reason.

A required assignment that hasn't been assigned to the user doesn't block
  • required assignments are configured tenant-wide, but each assignment has its own target audience, so different teams can legitimately have different assignments. A committer outside an assignment's target audience will correctly come back not assigned to it. That's expected scoping, not a misconfiguration, so it's excluded from the compliance check rather than treated as a failure. The connector still logs a non-blocking ::warning:: naming any such assignments every time the gate runs, so it doesn't go unnoticed.

Fail-Open Behavior

ASPEN_GATE_FAIL_OPEN defaults to true, which covers only these infrastructure cases, never a real non-compliant answer:

  • the gate endpoint is unreachable, times out (10s), or returns non-2xx or unparseable JSON
  • the response has no result matching the committer's email
  • a result carries a per-user error (e.g. an unrecognized email, meaning Aspen couldn't determine compliance, as opposed to determining the committer is non-compliant)
  • a result is missing the compliant field entirely
  • the committer's email couldn't be resolved from the CI platform at all

Set ASPEN_GATE_FAIL_OPEN=false to block CI whenever the gate check can't be completed for any of the above, rather than letting the pipeline through.


PR/MR Comments

  • When a commit is blocked and ASPEN_GATE_COMMENT_ON_FAILURE is true (the default), Gating functionality posts the failure reason as a comment on the associated pull/merge request, so a developer sees _why_ their branch is blocked without leaving GitHub/GitLab. Comment failures (e.g. missing permissions) are logged as warnings and never override the underlying gate result. The pipeline still fails or passes based on the gate check itself.

  • Comments are skipped when there's no PR/MR context (e.g. a push pipeline); only the gate check runs.

For complete configuration options, see the Aspen Connector GitHub repository. For other questions, contact support@securityjourney.com.