Skip to content

05 Creating Server Policies

This chapter shows you how to design certificate policies that keep SSH access tight without slowing operators down. You will build policies that answer a simple question every time someone requests a certificate: should this request be allowed right now?

5.1 Policy Concepts

Policies are the decision engine behind certificate issuance. They let you express who can access which servers, as which principals, under which conditions.

Why this matters:

  • Offboarding is immediate at policy level, without touching each host.
  • High-risk systems can enforce stricter controls than low-risk systems.
  • Access decisions become explainable during audits.
graph TD
    A[Certificate request] --> B[Policies sorted by priority]
    B --> C{Enabled policy}
    C -- No --> D[Skip]
    C -- Yes --> E{Match tags servers users principals}
    E -- No --> D
    E -- Yes --> F{Time source IP and permit checks pass}
    F -- No --> G[Deny]
    F -- Yes --> H[Issue short-lived certificate]
    D --> I{More policies}
    G --> I
    I -- Yes --> C
    I -- No --> J[Final deny]

5.2 Prerequisites

Before you create policies, confirm the environment is ready.

Requirement Lab Staging Production
At least one joined server Recommended Required Required
Stable server tagging convention (prod, db, bastion) Recommended Required Required
Admin account with MANAGE_POLICIES Required Required Required
Team timezone decision documented Optional Recommended Required
Test user for allow/deny validation Recommended Required Required

Minimum permissions:

  • You need MANAGE_POLICIES (or ADMIN) to create, edit, and delete policies.

Policy list screen:

SSH Teams certificate policies list

5.3 Quick Start (Happy Path)

Build a baseline policy in five minutes:

  1. Open https://<hostname>/policies.
  2. Select New Policy.
  3. Name it prod-readonly-ops.
  4. Set Enabled=true, Priority=100.
  5. Set Tags=prod and Principals=ubuntu,deploy.
  6. Set a weekday window in local business hours.
  7. Save.
  8. Test one allowed request and one denied request.

Then add a stricter policy for critical hosts:

  1. Create bastion-admin-restricted.
  2. Use explicit Servers and specific Users.
  3. Add source IP constraints for your admin network.
  4. Give it a lower priority number than broad policies.
  5. Save and retest.

Result you want:

  • Broad policy covers common cases.
  • Strict policy takes precedence for high-risk assets.

If expected allow/deny behavior does not match, use 12-troubleshooting-handbook.md#125-policy-mismatch-and-access-denials.

5.4 Matching Inputs

Key Parameters Explained (Impact First)

Create/edit form:

SSH Teams create policy form

Matching fields and purpose:

  • Tags: use for scalable policies across groups of servers.
  • Servers: use for exact targeting of critical hosts.
  • Users: use for break-glass or admin-only flows.
  • Principals: controls the UNIX account embedded into certificates.

How matching is typically used:

  • Broad team policy: tags plus principals.
  • High-risk policy: explicit servers plus explicit users.

Operational tip:

  • Keep tags consistent (prod, db, bastion) so policy intent stays readable.

5.5 Timezone and Time Restriction Semantics

Time controls decide when a valid request is still denied.

Time controls include three pieces:

  • Policy Timezone (optional): fixed IANA timezone such as Europe/London.
  • Use issuing user's timezone: if enabled, user timezone overrides fixed/server timezone when available.
  • Time Restrictions: day/time windows in DAY,HH:mm,HH:mm form.

Supported day values include:

  • MON to SUN
  • WEEKDAYS
  • WEEKEND
  • ALL_WEEK

Validation behavior:

  • Invalid timezone values are rejected.
  • Invalid day token in time restrictions is rejected.
  • Invalid restriction format (not DAY,HH:mm,HH:mm) is rejected.

5.6 Expiry, Source IP Constraints, Force Command, Permit Flags

Constraint fields:

  • Expiry Date: policy validity cutoff (yyyy-MM-dd).
  • Source IP Constraints: IPv4/IPv6 and CIDR allow-list entries.
  • Force Command: command forced at SSH session start.
  • Permit flags:
    • Permit X11
    • Permit Forwarding
    • Permit PTY
    • Permit User RC

Recommended production defaults:

  • Keep permit flags minimal; enable only what workloads need.
  • Use source IP constraints for admin and break-glass policies.
  • Add policy Notes describing owner, rationale, and review date.

5.7 Common Policy Patterns

Pattern When to use Core settings
Team baseline access Most environments Tags=prod, Principals=ubuntu,deploy, business-hour window
Bastion-only admin access Privileged gateways Explicit Servers, explicit Users, source IP allow-list
Emergency break-glass Incident response Highest priority, narrow user list, short expiry date
Automation account policy CI/CD access Service users, fixed principals, restricted source CIDRs

5.8 Policy CRUD Workflow

Create:

  1. Open https://<hostname>/policies.
  2. Select New Policy.
  3. Fill required fields (Policy Name, matching scope, constraints).
  4. Select Create Policy.

Update:

  1. Open policies list.
  2. Select Edit on target policy.
  3. Apply changes and select Update Policy.

Delete:

  1. Select Delete on policy row.
  2. Confirm delete prompt.

Quick verification after save:

  • Policy appears in list with expected Priority and Status.
  • Target users/servers can request certificates only under intended conditions.

5.9 Conflict and Versioning Behavior

SSH Teams applies optimistic locking on update using a policy version field.

If two admins edit the same policy concurrently:

  • First save succeeds.
  • Later stale save is rejected with a conflict message prompting refresh/retry.

Operational guidance:

  • Keep edits small and atomic.
  • Refresh list/form before high-impact changes.
  • Use notes/change logs outside the app for audit-friendly handoffs.

5.10 Policy Validation and Troubleshooting

Common issues and resolutions:

  • Policy not visible or action denied:

    • Ensure account has MANAGE_POLICIES permission.
  • Validation error on save:

    • Check timezone uses valid IANA name.
    • Check expiry format is yyyy-MM-dd.
    • Check time restriction format is DAY,HH:mm,HH:mm.
  • Expected access not granted:

    • Verify target server tags and server selection.
    • Verify user selection and principals list.
    • Verify date/time/source-IP constraints are actually satisfied.
  • Changes appear lost after concurrent edits:

    • Refresh page and reapply on latest version (version conflict protection).

Runbook check after policy rollout:

  • Test one allowed scenario and one denied scenario.
  • Confirm denial reason aligns with policy intent.

5.11 Pro Tip and Common Gotcha

Pro tip:

  • Start with two policies only: one broad baseline plus one strict high-risk policy. Expand only after you have validated real access patterns.

Common gotcha:

  • Teams often set correct tag matching but forget principal matching. If the requested principal is not allowed, issuance still fails even when user and server look correct.