Skip to content

Commit c3d15f3

Browse files
committed
docs: add README
1 parent 0e3f397 commit c3d15f3

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed

README.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Andrvotr: service delegation plugin for Shibboleth IdP
2+
3+
Andrvotr allows one service to sign in to another service on behalf of the user.
4+
5+
The IdP administrator can define pairs of "front services" and "back services". When any *user* **U** signs in to a given *front service* **F**, the server of **F** can ask the IdP to sign in to its *back service* **B** on behalf of **U**, and send authenticated HTTP requests to the server of **B** in the name of **U**.
6+
7+
## Deployment requirements (limitations)
8+
9+
This is a list of facts that Andrvotr requires from its environment. They must be satisfied in order to successfully deploy and use Andrvotr.
10+
11+
- The front service and back service must be SAML Service Providers (SP). They must be connected to the same SAML Identity Provider (IdP).
12+
- The back service must use the `HTTP-Redirect` binding for the SAML request and `HTTP-POST` for the SAML response. (This is the most common scenario.)
13+
- The IdP must be configured to use server-side session storage.
14+
I.e., `idp.session.StorageService` must be set to something other than `shibboleth.ClientSessionStorageService` or `shibboleth.ClientPersistentStorageService`.
15+
- If any "intercept" page is shown during back service sign in (e.g. attribute consent, terms of use, expiring password), the front service won't gain access.
16+
- Direct server-to-server connections with HTTPS on port 443 must be possible. (It's only mentioned here because the base SAML protocol doesn't strictly require it.)
17+
18+
## Design requirements (features)
19+
20+
This is a list of design requirements that Andrvotr meets. In contrast to the list of limitations, they say that Andrvotr is required to work regardless of how something is configured.
21+
22+
- The front service and back service can be written in any language and use any SAML SP software.
23+
- The SPs don't have to support the ECP profile or any SAML protocol extensions.
24+
- The process is invisible to the user and the back service. They do not have to approve it or know that it happens. The IdP administrator solely decides which front services and back services are allowed to connect.
25+
- The IdP can run on either Jetty or Tomcat.
26+
- The IdP does not have to be a single server, it can be a cluster.
27+
- The IdP does not have to handle mutual TLS or listen on port 8433.
28+
- `idp.consent.StorageService` can have any configured value, it doesn't have to be server-side storage.
29+
- The front service must not gain more privileges than necessary (e.g. signing in to any service or as any user).
30+
31+
## How it works
32+
33+
The front service receives an "Andrvotr Authority Token" from the IdP as a SAML attribute inside its SAML assertion. The token is essentially an encrypted tuple of (front service entity ID, user's IdP session cookies, expiration timestamp). It identifies a specific user accessing a specific front service at a specific point in time. It can be used to exchange SAML requests for SAML responses.
34+
35+
The front service then sends a login request to the back service, thus starting a normal SP-initiated SAML web flow. It follows redirects and maintains a cookie jar like real browsers. The back service responds with a HTTP redirect containing an encoded SAML request. This redirect would normally lead to the IdP's sign in form page.
36+
37+
Instead of following this redirect, the front service sends a special request to the IdP, asking Andrvotr to generate an artificial SAML response for this SAML request and Andrvotr Authority Token. If the request is valid and this front to back service connection is allowed, Andrvotr returns a SAML response. This is implemented with a nested request from the IdP to itself. The SAML response is just like what it would be if this user would sign into the back service directly.
38+
39+
The front service forwards this SAML response to the back service, receiving a session cookie and completing the sign in.
40+
41+
The key benefit of this design is that it requires zero changes to the back service, which just sees normal SAML flow. The cost is a moderate amount of front service complexity. If this is not a requirement you have, Andrvotr might not be the right solution for you.
42+
43+
<!-- TODO: Add a diagram. -->
44+
45+
## IdP setup
46+
47+
1. Look up the latest plugin version on the [Releases page](https://github.com/fmfi-svt/andrvotr/releases).
48+
49+
2. Install the plugin:
50+
51+
```shell
52+
/opt/shibboleth-idp/bin/plugin.sh -i https://github.com/fmfi-svt/andrvotr/releases/download/vX.Y.Z/idp-plugin-andrvotr-X.Y.Z.tar.gz
53+
```
54+
55+
(`-i` accepts a URL or a local path. Both `tar.gz` and `tar.gz.asc` are needed.)
56+
57+
3. Edit `/opt/shibboleth-idp/conf/attribute-resolver.xml` and add this code:
58+
59+
(To keep the file nicely sorted, it is suggested to insert it below the last `</AttributeDefinition>` line and above the `<!-- Data Connectors -->` line.)
60+
61+
```xml
62+
<AttributeDefinition id="andrvotrAuthorityToken"
63+
xsi:type="ContextDerivedAttribute"
64+
attributeValuesFunctionRef="andrvotr.AuthorityTokenGenerator">
65+
<AttributeEncoder xsi:type="SAML2String"
66+
name="tag:fmfi-svt.github.io,2024:andrvotr-authority-token"
67+
encodeType="false" />
68+
</AttributeDefinition>
69+
```
70+
71+
4. Edit `/opt/shibboleth-idp/conf/attribute-filter.xml` and add this line to the `alwaysRelease` policy:
72+
73+
```xml
74+
<AttributeRule attributeID="andrvotrAuthorityToken" permitAny="true" />
75+
```
76+
77+
Example:
78+
79+
```xml
80+
<AttributeFilterPolicy id="alwaysRelease">
81+
<PolicyRequirementRule xsi:type="ANY" />
82+
83+
<AttributeRule attributeID="otherAttributeFoo" permitAny="true" />
84+
<AttributeRule attributeID="otherAttributeBar" permitAny="true" />
85+
<AttributeRule attributeID="andrvotrAuthorityToken" permitAny="true" />
86+
</AttributeFilterPolicy>
87+
```
88+
89+
(Explanation: The attribute generator only produces a value for front services, configured in the next step.
90+
Even though the attribute is in `alwaysRelease`, normal services won't receive it.)
91+
92+
5. Look up the SP entity ID of one or more front services and back services you want to connect.
93+
94+
6. Use e.g. `base64 /dev/urandom | head -c32` to generate a random "API key" for each front service.
95+
96+
(Explanation: These API keys act as shared secrets between the IdP and each front service.
97+
Andrvotr Authority Tokens are the main authorization mechanism, but API keys exist as a simple additional precaution.)
98+
99+
7. Edit `/opt/shibboleth-idp/conf/idp.properties` and add this, using your entity IDs and API keys:
100+
101+
```ini
102+
andrvotr.allowedConnections=[ \
103+
FRONT_SERVICE_1>>BACK_SERVICE_1 \
104+
FRONT_SERVICE_2>>BACK_SERVICE_2 \
105+
... \
106+
]
107+
108+
andrvotr.apiKeys=[ \
109+
FRONT_SERVICE_1##API_KEY_1 \
110+
FRONT_SERVICE_2##API_KEY_2 \
111+
... \
112+
]
113+
```
114+
115+
You can change this configuration at any time.
116+
117+
Entity IDs can repeat in andrvotr.allowedConnections
118+
(e.g. if one front service can connect to multiple back services or vice versa)
119+
and in andrvotr.apiKeys (e.g. to accept multiple API keys during key rotation).
120+
121+
If you're worried about other users on the IdP server, you can put andrvotr.apiKeys in
122+
`/opt/shibboleth-idp/credentials/secrets.properties` instead of `/opt/shibboleth-idp/conf/idp.properties`.
123+
The only difference is chmod 600 vs 644.
124+
125+
8. Restart your servlet container.
126+
127+
9. Send the API keys to the developers/maintainers of your front services.
128+
129+
## Building from source
130+
131+
1. Install [Java](https://docs.aws.amazon.com/corretto/).
132+
133+
2. Install [Maven](https://maven.apache.org/install.html).
134+
135+
3. ```shell
136+
mkdir /path/to/andrvotr-development
137+
cd /path/to/andrvotr-development
138+
139+
git clone https://github.com/fmfi-svt/andrvotr.git
140+
141+
mkdir -m700 gpgdir
142+
GNUPGHOME=gpgdir gpg --full-generate-key
143+
# Is this correct? (y/N) y
144+
# Real name: My test key
145+
# Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
146+
# Leave everything else blank / default
147+
148+
GNUPGHOME=gpgdir gpg --export --armor > gpgpublic.asc
149+
```
150+
151+
4. Build with:
152+
153+
```shell
154+
cd /path/to/andrvotr-development/andrvotr
155+
GNUPGHOME=../gpgdir MAVEN_GPG_PUBLIC_KEY="$(cat ../gpgpublic.asc)" mvn verify
156+
```
157+
158+
Install with:
159+
160+
```shell
161+
sudo -u {USER} /opt/shibboleth-idp/bin/plugin.sh -i $PWD/andrvotr-dist/target/idp-plugin-andrvotr-*-SNAPSHOT.tar.gz --noCheck
162+
```
163+
164+
<!-- TODO: ## Developing compatible front services -->
165+
166+
<!-- TODO: ## Similar projects -->

0 commit comments

Comments
 (0)