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(orADMIN) to create, edit, and delete policies.
Policy list screen:

5.3 Quick Start (Happy Path)
Build a baseline policy in five minutes:
- Open
https://<hostname>/policies. - Select
New Policy. - Name it
prod-readonly-ops. - Set
Enabled=true,Priority=100. - Set
Tags=prodandPrincipals=ubuntu,deploy. - Set a weekday window in local business hours.
- Save.
- Test one allowed request and one denied request.
Then add a stricter policy for critical hosts:
- Create
bastion-admin-restricted. - Use explicit
Serversand specificUsers. - Add source IP constraints for your admin network.
- Give it a lower priority number than broad policies.
- 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:

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 asEurope/London.Use issuing user's timezone: if enabled, user timezone overrides fixed/server timezone when available.Time Restrictions: day/time windows inDAY,HH:mm,HH:mmform.
Supported day values include:
MONtoSUNWEEKDAYSWEEKENDALL_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 X11Permit ForwardingPermit PTYPermit 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
Notesdescribing 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:
- Open
https://<hostname>/policies. - Select
New Policy. - Fill required fields (
Policy Name, matching scope, constraints). - Select
Create Policy.
Update:
- Open policies list.
- Select
Editon target policy. - Apply changes and select
Update Policy.
Delete:
- Select
Deleteon policy row. - Confirm delete prompt.
Quick verification after save:
- Policy appears in list with expected
PriorityandStatus. - 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_POLICIESpermission.
- Ensure account has
-
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.