Skip to content

Commit a5660a2

Browse files
Copilotbbockelm
andcommitted
Add documentation and example config for AccHttpCallout plugin
Co-authored-by: bbockelm <1093447+bbockelm@users.noreply.github.com>
1 parent 2b6175c commit a5660a2

File tree

2 files changed

+202
-0
lines changed

2 files changed

+202
-0
lines changed

README.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ The plugins in the repository include:
1313
in the core XRootD (with the addition of making in-progress files not-visible in the namespace).
1414
- `XrdN2NPrefix`: A Name2Name (N2N) plugin that performs path prefix substitution,
1515
allowing logical paths to be mapped to different physical paths on disk.
16+
- `XrdAccHttpCallout`: An authorization plugin that makes HTTP callouts to an external service
17+
to determine access permissions.
1618

1719

1820
## Building and Installing
@@ -354,6 +356,159 @@ forward, while `pfn2lfn` (physical to logical) applies them in reverse.
354356
**Note**: When used with `oss.localroot`, the N2N plugin automatically prepends the localroot
355357
to physical paths returned by `lfn2pfn()`.
356358

359+
### Configure the AccHttpCallout Authorization Plugin
360+
361+
The AccHttpCallout plugin provides HTTP-based authorization callouts to an external service.
362+
This allows for flexible, centralized authorization logic implemented in any language that
363+
can serve HTTP requests.
364+
365+
To load the plugin, use the `acc.authlib` directive:
366+
367+
```
368+
acc.authlib libXrdAccHttpCallout.so
369+
```
370+
371+
(an absolute path may be given if `libXrdAccHttpCallout-5.so` does not reside in a system directory)
372+
373+
There are several configuration directives for the AccHttpCallout module:
374+
375+
```
376+
acchttpcallout.endpoint <url>
377+
acchttpcallout.cache_ttl_positive <seconds>
378+
acchttpcallout.cache_ttl_negative <seconds>
379+
acchttpcallout.passthrough [true|false]
380+
acchttpcallout.trace [all|error|warning|info|debug|none]
381+
```
382+
383+
- `acchttpcallout.endpoint`: **(Required)** The HTTP(S) endpoint URL that will be called for
384+
authorization decisions. The plugin will make HTTP GET requests to this endpoint with query
385+
parameters for the path and operation (verb).
386+
387+
Example:
388+
```
389+
acchttpcallout.endpoint https://auth.example.com/authorize
390+
```
391+
392+
- `acchttpcallout.cache_ttl_positive`: Cache time-to-live in seconds for positive (authorized)
393+
responses. Default is 60 seconds. This reduces load on the authorization service by caching
394+
successful authorization decisions.
395+
396+
Example:
397+
```
398+
acchttpcallout.cache_ttl_positive 120
399+
```
400+
401+
- `acchttpcallout.cache_ttl_negative`: Cache time-to-live in seconds for negative (denied)
402+
responses. Default is 30 seconds. This prevents repeated unauthorized requests from
403+
overwhelming the authorization service.
404+
405+
Example:
406+
```
407+
acchttpcallout.cache_ttl_negative 60
408+
```
409+
410+
- `acchttpcallout.passthrough`: Controls behavior when authorization fails. If `true`, the
411+
plugin will pass the request to the next configured authorization plugin (if any). If `false`
412+
(default), authorization failures result in immediate denial.
413+
414+
Example:
415+
```
416+
acchttpcallout.passthrough false
417+
```
418+
419+
- `acchttpcallout.trace`: Controls logging verbosity. Can be specified multiple times (values
420+
are additive) and multiple values can be given per line.
421+
422+
Example:
423+
```
424+
acchttpcallout.trace info
425+
```
426+
427+
#### HTTP Callout Protocol
428+
429+
When a client attempts to access a resource, the plugin makes an HTTP GET request to the
430+
configured endpoint with the following query parameters:
431+
432+
- `path`: The URL-encoded path being accessed (e.g., `/store/data/file.txt`)
433+
- `verb`: The HTTP/WebDAV verb corresponding to the operation (e.g., `GET`, `PUT`, `DELETE`)
434+
435+
The bearer token from the client is passed in the `Authorization` header:
436+
437+
```
438+
Authorization: Bearer <token>
439+
```
440+
441+
The authorization service should respond with:
442+
443+
- **200 OK**: Access is granted
444+
- **401 Unauthorized** or **403 Forbidden**: Access is denied
445+
- **5xx Server Error**: Error executing authorization (treated as failure)
446+
447+
#### Response Format
448+
449+
The response body may optionally contain JSON data with additional information:
450+
451+
```json
452+
{
453+
"authorizations": [
454+
{
455+
"verb": "GET",
456+
"prefixes": ["/store/data", "/store/mc"]
457+
}
458+
],
459+
"user": "jdoe",
460+
"group": "physicists"
461+
}
462+
```
463+
464+
- `authorizations`: An array of additional path prefixes that are authorized for the token.
465+
These are cached to avoid redundant callouts for related paths.
466+
- `verb`: The HTTP/WebDAV verb (e.g., `GET`, `PUT`)
467+
- `prefixes`: Array of path prefixes authorized for this verb
468+
469+
- `user`: Username to add to the security context (optional)
470+
- `group`: Group name to add to the security context (optional)
471+
472+
#### Operation to Verb Mapping
473+
474+
The plugin maps XRootD operations to HTTP/WebDAV verbs as follows:
475+
476+
| XRootD Operation | HTTP/WebDAV Verb |
477+
|-----------------|------------------|
478+
| Read | GET |
479+
| Readdir | PROPFIND |
480+
| Stat | HEAD |
481+
| Update/Create | PUT |
482+
| Delete | DELETE |
483+
| Mkdir | MKCOL |
484+
| Rename/Insert | MOVE |
485+
486+
#### Complete Example Configuration
487+
488+
```
489+
# Enable the HTTP protocol
490+
xrd.protocol http:1094 libXrdHttp.so
491+
492+
# Load the authorization plugin
493+
acc.authlib libXrdAccHttpCallout.so
494+
495+
# Configure the authorization endpoint
496+
acchttpcallout.endpoint https://pelican-auth.example.com/api/v1/authorize
497+
498+
# Configure caching (2 minutes for positive, 1 minute for negative)
499+
acchttpcallout.cache_ttl_positive 120
500+
acchttpcallout.cache_ttl_negative 60
501+
502+
# Don't pass through to other auth plugins on failure
503+
acchttpcallout.passthrough false
504+
505+
# Enable info-level logging
506+
acchttpcallout.trace info
507+
508+
# Export paths
509+
all.export /store
510+
```
511+
357512
## Startup and Testing
358513

359514
Assuming you named the config file `xrootd-http.cfg`, as a non-rootly user run:
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Example XRootD configuration using AccHttpCallout authorization plugin
2+
#
3+
# This configuration demonstrates how to set up XRootD with HTTP-based
4+
# authorization callouts to an external authorization service.
5+
6+
# Enable the HTTP protocol on port 1094
7+
xrd.protocol http:1094 libXrdHttp.so
8+
9+
# Load the AccHttpCallout authorization plugin
10+
acc.authlib libXrdAccHttpCallout.so
11+
12+
# Configure the authorization endpoint
13+
# This is the URL of your authorization service that will receive HTTP GET requests
14+
# with query parameters: ?path=<url-encoded-path>&verb=<HTTP-verb>
15+
# The bearer token will be passed in the Authorization header
16+
acchttpcallout.endpoint https://auth.example.com/api/v1/authorize
17+
18+
# Cache time-to-live for positive (authorized) responses in seconds
19+
# Default: 60 seconds
20+
# Increase this value to reduce load on your authorization service
21+
acchttpcallout.cache_ttl_positive 120
22+
23+
# Cache time-to-live for negative (denied) responses in seconds
24+
# Default: 30 seconds
25+
# This prevents repeated unauthorized requests from overwhelming your service
26+
acchttpcallout.cache_ttl_negative 60
27+
28+
# Passthrough behavior when authorization fails
29+
# - true: Pass the request to the next configured authorization plugin
30+
# - false (default): Immediately deny access on failure
31+
acchttpcallout.passthrough false
32+
33+
# Logging verbosity
34+
# Options: all, error, warning, info, debug, none
35+
acchttpcallout.trace info
36+
37+
# Export paths that XRootD will serve
38+
# Users can access files under these paths (subject to authorization)
39+
all.export /store
40+
all.export /data
41+
42+
# Optional: Disable async mode if needed
43+
# (Some plugins may not work in async mode)
44+
xrootd.async off
45+
46+
# Optional: Set the port for admin interface
47+
# xrd.port 1094

0 commit comments

Comments
 (0)