Skip to content

Commit 4956f43

Browse files
Update documentation for authentication
1 parent 5fb9dba commit 4956f43

File tree

4 files changed

+846
-0
lines changed

4 files changed

+846
-0
lines changed

docs/authentication.md

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# Authentication Configuration
2+
3+
ServiceControl instances can be configured to require JWT authentication using OpenID Connect (OIDC). This enables integration with identity providers like Microsoft Entra ID (Azure AD), Okta, Auth0, and other OIDC-compliant providers.
4+
5+
## Configuration
6+
7+
ServiceControl instances can be configured via environment variables or App.config. Each instance type uses a different prefix.
8+
9+
### Environment Variables
10+
11+
| Instance | Prefix |
12+
|----------|--------|
13+
| ServiceControl (Primary) | `SERVICECONTROL_` |
14+
| ServiceControl.Audit | `SERVICECONTROL_AUDIT_` |
15+
| ServiceControl.Monitoring | `MONITORING_` |
16+
17+
#### Core Settings
18+
19+
| Setting | Default | Description |
20+
|---------|---------|-------------|
21+
| `{PREFIX}AUTHENTICATION_ENABLED` | `false` | Enable JWT authentication |
22+
| `{PREFIX}AUTHENTICATION_AUTHORITY` | (none) | OpenID Connect authority URL (e.g., `https://login.microsoftonline.com/{tenant-id}/v2.0`) |
23+
| `{PREFIX}AUTHENTICATION_AUDIENCE` | (none) | The audience identifier (typically your API identifier or client ID) |
24+
25+
#### Validation Settings
26+
27+
| Setting | Default | Description |
28+
|---------|---------|-------------|
29+
| `{PREFIX}AUTHENTICATION_VALIDATEISSUER` | `true` | Validate the token issuer |
30+
| `{PREFIX}AUTHENTICATION_VALIDATEAUDIENCE` | `true` | Validate the token audience |
31+
| `{PREFIX}AUTHENTICATION_VALIDATELIFETIME` | `true` | Validate token expiration |
32+
| `{PREFIX}AUTHENTICATION_VALIDATEISSUERSIGNINGKEY` | `true` | Validate the signing key |
33+
| `{PREFIX}AUTHENTICATION_REQUIREHTTPSMETADATA` | `true` | Require HTTPS for OIDC metadata endpoint |
34+
35+
#### ServicePulse Settings (Primary Instance Only)
36+
37+
These settings are required on the primary ServiceControl instance to provide authentication configuration to ServicePulse clients.
38+
39+
| Setting | Default | Description |
40+
|---------|---------|-------------|
41+
| `{PREFIX}AUTHENTICATION_SERVICEPULSE_CLIENTID` | (none) | Client ID for ServicePulse application |
42+
| `{PREFIX}AUTHENTICATION_SERVICEPULSE_AUTHORITY` | (none) | Authority URL for ServicePulse (defaults to main Authority if not set) |
43+
| `{PREFIX}AUTHENTICATION_SERVICEPULSE_APISCOPES` | (none) | JSON array of API scopes (e.g., `["api://servicecontrol/access_as_user"]`) |
44+
45+
### App.config
46+
47+
| Instance | Key Prefix |
48+
|----------|------------|
49+
| ServiceControl (Primary) | `ServiceControl/` |
50+
| ServiceControl.Audit | `ServiceControl.Audit/` |
51+
| ServiceControl.Monitoring | `Monitoring/` |
52+
53+
```xml
54+
<appSettings>
55+
<!-- Core Authentication Settings -->
56+
<add key="ServiceControl/Authentication.Enabled" value="true" />
57+
<add key="ServiceControl/Authentication.Authority" value="https://login.microsoftonline.com/{tenant-id}/v2.0" />
58+
<add key="ServiceControl/Authentication.Audience" value="api://servicecontrol" />
59+
60+
<!-- Validation Settings (defaults shown - recommended for production) -->
61+
<add key="ServiceControl/Authentication.ValidateIssuer" value="true" />
62+
<add key="ServiceControl/Authentication.ValidateAudience" value="true" />
63+
<add key="ServiceControl/Authentication.ValidateLifetime" value="true" />
64+
<add key="ServiceControl/Authentication.ValidateIssuerSigningKey" value="true" />
65+
<add key="ServiceControl/Authentication.RequireHttpsMetadata" value="true" />
66+
67+
<!-- ServicePulse Settings (Primary Instance Only) -->
68+
<add key="ServiceControl/Authentication.ServicePulse.ClientId" value="{servicepulse-client-id}" />
69+
<add key="ServiceControl/Authentication.ServicePulse.ApiScopes" value="[&quot;api://servicecontrol/access_as_user&quot;]" />
70+
</appSettings>
71+
```
72+
73+
## Examples
74+
75+
### Microsoft Entra ID (Azure AD)
76+
77+
```cmd
78+
set SERVICECONTROL_AUTHENTICATION_ENABLED=true
79+
set SERVICECONTROL_AUTHENTICATION_AUTHORITY=https://login.microsoftonline.com/{tenant-id}/v2.0
80+
set SERVICECONTROL_AUTHENTICATION_AUDIENCE=api://servicecontrol
81+
set SERVICECONTROL_AUTHENTICATION_SERVICEPULSE_CLIENTID={servicepulse-client-id}
82+
set SERVICECONTROL_AUTHENTICATION_SERVICEPULSE_APISCOPES=["api://servicecontrol/access_as_user"]
83+
```
84+
85+
### Docker Example
86+
87+
```cmd
88+
docker run -p 33333:33333 -e SERVICECONTROL_AUTHENTICATION_ENABLED=true -e SERVICECONTROL_AUTHENTICATION_AUTHORITY=https://login.microsoftonline.com/{tenant-id}/v2.0 -e SERVICECONTROL_AUTHENTICATION_AUDIENCE=api://servicecontrol -e SERVICECONTROL_AUTHENTICATION_SERVICEPULSE_CLIENTID={servicepulse-client-id} -e "SERVICECONTROL_AUTHENTICATION_SERVICEPULSE_APISCOPES=[\"api://servicecontrol/.default\"]" particular/servicecontrol:latest
89+
```
90+
91+
### Audit and Monitoring Instances
92+
93+
Audit and Monitoring instances don't require ServicePulse settings:
94+
95+
```cmd
96+
set SERVICECONTROL_AUDIT_AUTHENTICATION_ENABLED=true
97+
set SERVICECONTROL_AUDIT_AUTHENTICATION_AUTHORITY=https://login.microsoftonline.com/{tenant-id}/v2.0
98+
set SERVICECONTROL_AUDIT_AUTHENTICATION_AUDIENCE=api://servicecontrol
99+
```
100+
101+
```cmd
102+
set MONITORING_AUTHENTICATION_ENABLED=true
103+
set MONITORING_AUTHENTICATION_AUTHORITY=https://login.microsoftonline.com/{tenant-id}/v2.0
104+
set MONITORING_AUTHENTICATION_AUDIENCE=api://servicecontrol
105+
```
106+
107+
## How It Works
108+
109+
When authentication is enabled:
110+
111+
1. Most API requests must include a valid JWT bearer token in the `Authorization` header
112+
2. ServiceControl validates the token against the configured authority
113+
3. The token must have the correct audience and not be expired
114+
4. ServicePulse retrieves authentication configuration from the `/api/authentication/configuration` endpoint
115+
116+
### Anonymous Endpoints
117+
118+
The following endpoints are accessible without authentication, even when authentication is enabled:
119+
120+
| Endpoint | Purpose |
121+
|----------|---------|
122+
| `/api` | API root/discovery - returns available endpoints and API information |
123+
| `/api/authentication/configuration` | Returns authentication configuration for clients like ServicePulse |
124+
125+
These endpoints must remain accessible so clients can discover API capabilities and obtain the authentication configuration needed to acquire tokens.
126+
127+
### Request Flow
128+
129+
```mermaid
130+
flowchart TD
131+
Client[Client Request] --> Header[Authorization: Bearer token]
132+
Header --> Validate{ServiceControl validates token}
133+
134+
Validate --> |Valid| Process[Request processed]
135+
Validate --> |Invalid| Reject[401 Unauthorized]
136+
137+
subgraph Validation
138+
V1[Issuer matches Authority]
139+
V2[Audience matches configured]
140+
V3[Token not expired]
141+
V4[Signature is valid]
142+
end
143+
144+
Validate -.-> Validation
145+
```
146+
147+
## Security Considerations
148+
149+
### HTTPS Recommended
150+
151+
When authentication is enabled, HTTPS is strongly recommended for production deployments. Without HTTPS, JWT tokens are transmitted in plain text and can be intercepted by attackers. Use either:
152+
153+
- **Direct HTTPS**: Configure ServiceControl with a certificate (see [HTTPS Configuration](https-configuration.md))
154+
- **Reverse Proxy**: Terminate SSL at a reverse proxy (NGINX, Traefik, cloud load balancer)
155+
156+
### Production Settings
157+
158+
The default validation settings are recommended for production:
159+
160+
| Setting | Recommendation |
161+
|---------|----------------|
162+
| `ValidateIssuer` | `true` - Prevents tokens from untrusted issuers |
163+
| `ValidateAudience` | `true` - Prevents tokens intended for other applications |
164+
| `ValidateLifetime` | `true` - Prevents expired tokens |
165+
| `ValidateIssuerSigningKey` | `true` - Ensures token signature is valid |
166+
| `RequireHttpsMetadata` | `true` - Ensures OIDC metadata is fetched securely |
167+
168+
### Development Settings
169+
170+
For local development with a test identity provider, you may need to relax some settings:
171+
172+
```cmd
173+
set SERVICECONTROL_AUTHENTICATION_REQUIREHTTPSMETADATA=false
174+
```
175+
176+
> **Warning:** Never disable validation settings in production. Doing so can expose your system to serious security vulnerabilities.
177+
178+
### HTTPS Requirement
179+
180+
When `RequireHttpsMetadata` is `true` (the default), the Authority URL must use HTTPS. This ensures that the OIDC metadata (including signing keys) is fetched over a secure connection.
181+
182+
## Configuring Identity Providers
183+
184+
### Microsoft Entra ID (Azure AD)
185+
186+
1. Register an application in Azure AD for ServiceControl API
187+
2. Register a separate application for ServicePulse (SPA)
188+
3. Configure API permissions and expose an API scope
189+
4. Set the Authority to `https://login.microsoftonline.com/{tenant-id}/v2.0`
190+
5. Set the Audience to your API application ID URI (e.g., `api://servicecontrol`)
191+
192+
### Other OIDC Providers
193+
194+
ServiceControl works with any OIDC-compliant provider. Configure:
195+
196+
- **Authority**: The issuer URL from your provider's OIDC discovery document
197+
- **Audience**: The identifier configured for your API in the provider
198+
199+
## Testing Other Instances
200+
201+
The primary ServiceControl instance requires ServicePulse settings because it serves the `/api/auth/config` endpoint that ServicePulse uses to configure its authentication. Audit and Monitoring instances only need the core authentication settings.
202+
203+
| Instance | Requires ServicePulse Settings |
204+
|----------|-------------------------------|
205+
| ServiceControl (Primary) | Yes |
206+
| ServiceControl.Audit | No |
207+
| ServiceControl.Monitoring | No |
208+
209+
## See Also
210+
211+
- [Forwarded Headers Configuration](forwarded-headers.md) - Configure forwarded headers when behind a reverse proxy
212+
- [HTTPS Configuration](https-configuration.md) - Configure direct HTTPS

docs/forwarded-headers.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Forwarded Headers Configuration
2+
3+
When ServiceControl instances are deployed behind a reverse proxy (like NGINX, Traefik, or a cloud load balancer) that terminates SSL/TLS, you need to configure forwarded headers so ServiceControl correctly understands the original client request.
4+
5+
## Configuration
6+
7+
ServiceControl instances can be configured via environment variables or App.config. Each instance type uses a different prefix.
8+
9+
### Environment Variables
10+
11+
| Instance | Prefix |
12+
|----------|--------|
13+
| ServiceControl (Primary) | `SERVICECONTROL_` |
14+
| ServiceControl.Audit | `SERVICECONTROL_AUDIT_` |
15+
| ServiceControl.Monitoring | `MONITORING_` |
16+
17+
| Setting | Default | Description |
18+
|---------|---------|-------------|
19+
| `{PREFIX}FORWARDEDHEADERS_ENABLED` | `true` | Enable forwarded headers processing |
20+
| `{PREFIX}FORWARDEDHEADERS_TRUSTALLPROXIES` | `true` | Trust all proxies (auto-disabled if known proxies/networks set) |
21+
| `{PREFIX}FORWARDEDHEADERS_KNOWNPROXIES` | (none) | Comma-separated IP addresses of trusted proxies |
22+
| `{PREFIX}FORWARDEDHEADERS_KNOWNNETWORKS` | (none) | Comma-separated CIDR networks (e.g., `10.0.0.0/8,172.16.0.0/12`) |
23+
24+
### App.config
25+
26+
| Instance | Key Prefix |
27+
|----------|------------|
28+
| ServiceControl (Primary) | `ServiceControl/` |
29+
| ServiceControl.Audit | `ServiceControl.Audit/` |
30+
| ServiceControl.Monitoring | `Monitoring/` |
31+
32+
```xml
33+
<appSettings>
34+
<add key="ServiceControl/ForwardedHeaders.Enabled" value="true" />
35+
<add key="ServiceControl/ForwardedHeaders.TrustAllProxies" value="false" />
36+
<add key="ServiceControl/ForwardedHeaders.KnownProxies" value="127.0.0.1,10.0.0.5" />
37+
<add key="ServiceControl/ForwardedHeaders.KnownNetworks" value="10.0.0.0/8,172.16.0.0/12" />
38+
</appSettings>
39+
```
40+
41+
## Examples
42+
43+
### Trust all proxies (default, suitable for containers)
44+
45+
```cmd
46+
docker run -p 33333:33333 -e SERVICECONTROL_FORWARDEDHEADERS_ENABLED=true particular/servicecontrol:latest
47+
```
48+
49+
### Restrict to specific proxies
50+
51+
```cmd
52+
docker run -p 33333:33333 -e SERVICECONTROL_FORWARDEDHEADERS_ENABLED=true -e SERVICECONTROL_FORWARDEDHEADERS_KNOWNPROXIES=127.0.0.1,10.0.0.5 particular/servicecontrol:latest
53+
```
54+
55+
### Restrict to specific networks
56+
57+
```cmd
58+
docker run -p 33333:33333 -e SERVICECONTROL_FORWARDEDHEADERS_ENABLED=true -e SERVICECONTROL_FORWARDEDHEADERS_KNOWNNETWORKS=10.0.0.0/8,172.16.0.0/12 particular/servicecontrol:latest
59+
```
60+
61+
When `KNOWNPROXIES` or `KNOWNNETWORKS` are set, `TRUSTALLPROXIES` is automatically disabled.
62+
63+
## What Headers Are Processed
64+
65+
When enabled, ServiceControl processes:
66+
67+
- `X-Forwarded-For` - Original client IP address
68+
- `X-Forwarded-Proto` - Original protocol (http/https)
69+
- `X-Forwarded-Host` - Original host header
70+
71+
## HTTP to HTTPS Redirect
72+
73+
When using a reverse proxy that terminates SSL, you can configure ServiceControl to redirect HTTP requests to HTTPS. This works in combination with forwarded headers:
74+
75+
1. The reverse proxy forwards both HTTP and HTTPS requests to ServiceControl
76+
2. The proxy sets `X-Forwarded-Proto` to indicate the original protocol
77+
3. ServiceControl reads this header (via forwarded headers processing)
78+
4. If the original request was HTTP and redirect is enabled, ServiceControl returns a redirect to HTTPS
79+
80+
To enable HTTP to HTTPS redirect:
81+
82+
```cmd
83+
set SERVICECONTROL_HTTPS_REDIRECTHTTPTOHTTPS=true
84+
set SERVICECONTROL_HTTPS_PORT=443
85+
```
86+
87+
Or in App.config:
88+
89+
```xml
90+
<appSettings>
91+
<add key="ServiceControl/Https.RedirectHttpToHttps" value="true" />
92+
<add key="ServiceControl/Https.Port" value="443" />
93+
</appSettings>
94+
```
95+
96+
## Proxy Chain Behavior (ForwardLimit)
97+
98+
When processing `X-Forwarded-For` headers with multiple IPs (proxy chains), the behavior depends on trust configuration:
99+
100+
| Configuration | ForwardLimit | Behavior |
101+
|---------------|--------------|----------|
102+
| `TrustAllProxies = true` | `null` (no limit) | Processes all IPs, returns original client IP |
103+
| `TrustAllProxies = false` | `1` (default) | Processes only the last proxy IP |
104+
105+
For example, with `X-Forwarded-For: 203.0.113.50, 10.0.0.1, 192.168.1.1`:
106+
107+
- **TrustAllProxies = true**: Returns `203.0.113.50` (original client)
108+
- **TrustAllProxies = false**: Returns `192.168.1.1` (last proxy)
109+
110+
## Security Considerations
111+
112+
By default, `TrustAllProxies` is `true`, which is suitable for container deployments where the proxy is trusted infrastructure. For production deployments with untrusted networks, consider restricting to known proxies or networks to prevent header spoofing attacks.
113+
114+
### Forwarded Headers Behavior
115+
116+
When the proxy is trusted:
117+
118+
- `Request.Scheme` will be set from `X-Forwarded-Proto` (e.g., `https`)
119+
- `Request.Host` will be set from `X-Forwarded-Host` (e.g., `servicecontrol.example.com`)
120+
- Client IP will be available from `X-Forwarded-For`
121+
122+
When the proxy is **not** trusted (incorrect `KnownProxies`):
123+
124+
- `X-Forwarded-*` headers are **ignored** (not applied to the request)
125+
- `Request.Scheme` remains `http`
126+
- `Request.Host` remains the internal hostname
127+
- The request is still processed (not blocked)
128+
129+
## See Also
130+
131+
- [Local Forwarded Headers Testing](local-forward-headers-testing.md) - Test forwarded headers configuration with curl
132+
- [Local Reverse Proxy Testing](local-reverseproxy-testing.md) - Guide for testing with NGINX reverse proxy locally

0 commit comments

Comments
 (0)