Skip to content

Latest commit

 

History

History
149 lines (111 loc) · 6.94 KB

File metadata and controls

149 lines (111 loc) · 6.94 KB

Configuration Reference

VouchGate is configured entirely through Function App application settings. The deploy scripts (infra/deploy.sh / infra/deploy.ps1) provision these from infra/modules/functionapp.bicep, and the frontend reads a small subset from a generated frontend/authConfig.js. For local development, copy backend/local.settings.json.examplebackend/local.settings.json.


Backend application settings

Setting Purpose Default
TENANT_ID Entra ID tenant ID required
AUTH_CLIENT_ID App Registration client ID (Easy Auth / JWT audience) required
TABLE_STORAGE_CONNECTION_STRING Storage account holding both tables required
REQUESTS_TABLE_NAME Requests table name VouchGateRequests
AUDIT_TABLE_NAME Audit table name VouchGateAudit
GRAPH_API_ENDPOINT Microsoft Graph endpoint https://graph.microsoft.com
JUSTIFICATION_MIN_LENGTH Minimum justification length (chars) 10
MAX_DURATION_DAYS Maximum requestable access duration (days) 365
ESCALATION_DAYS Days a request may stay pending before fallback group members may also approve it 5
ESCALATION_REMINDER_CRON NCRONTAB schedule for the daily escalation reminder timer 0 0 7 * * *
APPROVER_FALLBACK_GROUP_ID Object ID of the fallback approver group. Required so users without a manager have an approver (also used for escalation). Set at deploy time from --fallback-group / -FallbackGroup. required
ALLOWED_GUEST_DOMAINS Comma-separated allow-list of guest email domains (empty = allow all) (empty)
BLOCKED_GUEST_DOMAINS Comma-separated block-list of guest email domains (empty = block none) (empty)
MAIL_SENDER Shared mailbox used as the sender for all notification mails required
PORTAL_URL Public URL of the portal, used for mail deep links (/?request={id}) and the invitation redirect Static Web App URL

The following runtime settings are also present (managed by the platform / deploy): AzureWebJobsStorage, FUNCTIONS_WORKER_RUNTIME, FUNCTIONS_EXTENSION_VERSION, WEBSITE_NODE_DEFAULT_VERSION, APPLICATIONINSIGHTS_CONNECTION_STRING, AZURE_LOG_LEVEL.

Frontend configuration (authConfig.js)

Generated by the deploy scripts from deployment outputs and read by the SPA as window.VOUCHGATE_CONFIG:

Key Purpose
msalClientId App Registration client ID
tenantId Entra ID tenant ID
apiBaseUrl Backend Function App base URL (no trailing slash)
apiScope api://{clientId}/access_as_user
justificationMinLength Mirrors the backend minimum (client-side hint only)
durationOptions Selectable durations, e.g. [30, 90, 180, 365]
defaultDuration Pre-selected duration in days

authConfig.js is gitignored, it is regenerated on every deploy and must never be committed with real tenant/client IDs.


Approval escalation

A request is normally decided by the requester's manager (resolved via Graph /users/{id}/manager), or, when the requester has no manager, by a member of the fallback approver group (APPROVER_FALLBACK_GROUP_ID).

If a request stays pending longer than ESCALATION_DAYS, members of the fallback approver group become additional valid approvers for it (including for manager-routed requests). This is enforced server-side in both the pending list (GET /api/requests?view=pending) and the decision endpoint (POST /api/requests/{id}/decision); eligibility is age-based and re-checked via Microsoft Graph on every call.

A daily timer function (escalationReminder, scheduled by ESCALATION_REMINDER_CRON) sends a single digest mail to the fallback group listing all pending requests past ESCALATION_DAYS that have not been escalated yet, then stamps escalatedAt on those requests so the reminder is not sent again. The mail is only stamped after a successful send, so a send failure is retried on the next run.

Decisions made through escalation are audited with approverType = fallback-escalation (versus manager or group).


Guest domain allow / block lists

ALLOWED_GUEST_DOMAINS and BLOCKED_GUEST_DOMAINS are comma-separated domain lists evaluated at request submission:

  • If the guest's email domain is in BLOCKED_GUEST_DOMAINS, the request is rejected (DOMAIN_BLOCKED).
  • If ALLOWED_GUEST_DOMAINS is non-empty and the domain is not in it, the request is rejected (DOMAIN_NOT_ALLOWED).
  • If ALLOWED_GUEST_DOMAINS is empty, all domains are allowed (subject to the block-list).

Example: ALLOWED_GUEST_DOMAINS = "partner.com,contractor.io".


Microsoft Graph permissions (Managed Identity)

Assigned by the deploy scripts to the Function App's system-assigned Managed Identity (application permissions, admin-consented):

Permission Why VouchGate needs it
User.Invite.All Create the guest via POST /invitations
User.ReadWrite.All Resolve the requester's manager; patch the guest (extensionAttribute13, employeeType, sponsors)
Mail.Send Send notification mails as MAIL_SENDER
GroupMember.Read.All Verify fallback approver group membership (checkMemberGroups) and resolve group member mailboxes for BCC notifications

The App Registration additionally has the delegated User.Read permission (admin-consented) for interactive sign-in.


Scoping Mail.Send (mandatory)

Mail.Send as an application permission is tenant-wide by default: the Managed Identity could send email as any mailbox. It must be restricted to the MAIL_SENDER mailbox using an Exchange Online Application Access Policy.

See docs/deployment.md for the full Connect-ExchangeOnline / New-ApplicationAccessPolicy / Test-ApplicationAccessPolicy walkthrough.


Access control (restricting who can use the portal)

By default every user in the tenant can sign in. Restrict access after deploy:

  1. Entra ID → Enterprise Applications → the VouchGate portal app.
  2. PropertiesAssignment required?YesSave.
  3. Users and groups → assign a dedicated security group (e.g. SG-VouchGate-Requesters).

Enforce MFA with a Conditional Access policy targeting the same group. See docs/deployment.md.


Lifecycle integration

On approval VouchGate stamps the approval expiry on the guest as extensionAttribute13 (ISO 8601) and sets employeeType = "VouchGate" and sponsors = requester. Expiry cleanup is handled externally by EntraID Guest User LifeCycle Management, which reads extensionAttribute13.

VouchGate never sets extensionAttribute15 = "ExcludeFromLCM", so every guest it provisions remains subject to the external lifecycle cleanup.