Skip to content

Commit 48f979f

Browse files
add SharedFlow for IAP securization
1 parent cd04aad commit 48f979f

File tree

16 files changed

+315
-2
lines changed

16 files changed

+315
-2
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Sharedflow gcp-token
2+
3+
## Description
4+
5+
Ce sharedflow va permettre de demander un jeton OAuth à Google en fonction du service account qui lui ai passé en paramètre.
6+
Une fois le token récupéré alors on le met en cache durant la durée définit dans le fichier de configuration _caches.json_ (peut être différent pour chaque environnement. Dans nos exemples cette valeur est de 10 seconde en dev, 60 secondes en test et 3500 secondes en prd).
7+
[Documentation Google](https://developers.google.com/identity/protocols/oauth2/service-account)
8+
9+
## Pré-requis
10+
Lors de l'utilisation de ce sharedflow dans un proxy il faut d'abord prévoir :
11+
12+
- Un sevice account qui a les droit d'appeler une API sur GCP via un IAP.
13+
- Le JSON de ce service account.
14+
- Créer une entrée dans le KVM chiffré *gcp-service-account-credentials* avec en clé le nom du projet et en valeur le contenu du JSON du service account.
15+
- Créer dans le proxy une variable nommée *private.credentialsjson* dont la valeur est le contenu du JSON du service account.
16+
17+
## Fonctionnement
18+
19+
Ce sharedflow exécute 7 policies d'affilées :
20+
- lc.gcp-token
21+
- js.extract-credentials
22+
- gjwt.generate-JWT
23+
- sc.gcp-oauth
24+
- ev.extract-json
25+
- am.add-authorization
26+
- pc.gcp-token
27+
28+
### lc.gcp-token
29+
30+
Cette policy vérifie si une valeur existe dans un cache dont le nom est composé :
31+
- nom de l'organisation
32+
- nom de l'environnement
33+
- nom du proxy
34+
- numéro de la révision
35+
- nom de la target
36+
Si une valeur est trouvée alors on instancie la valeur de la variable _google-credentials.id-token_ avec cette valeur.
37+
Cela permet d'éviter de demander un nouveau token si cette valeur est toujours présente (durée de cache encore valide).
38+
39+
** Les 4 étapes suivantes ne sont exécutées que si la variable _google-credentials.id-token_ n'est pas vide.**
40+
41+
### js.extract-credentials
42+
43+
Cette policy permet d'extraire chaque paire clé/valeur de la variable *private.credentialsjson* (qui contient le contenu du JSON du service account).
44+
45+
### gjwt.generate-JWT
46+
47+
Cette policy utilise les informations récupérées pour générer un jeton JWT. Ce jeton est inscrit dans la variable *output_jwt*.
48+
49+
### sc.gcp-oauth
50+
51+
Cette policy demande à GCP la création d'un jeton OAuth à partir du jeton JWT généré précédemment. Ce jeton est inscrit dans la variable *callout-token*.
52+
53+
### ev.extract-json
54+
55+
Cette policy extrait le jeton OAuth renvoyé précédemment et crée une variable *google-credentials.id-token*.
56+
57+
### am.add-authorization
58+
59+
Cette policy crée une en-tête *Authorization* dont la valeur est *Bearer * + le contenu de la variable _google-credentials.id-token_.
60+
61+
### pc.gcp-token
62+
63+
Cette policy met en cache la valeur de la variable _google-credentials.id-token_ dans un cache dont le nom est composé :
64+
- nom de l'organisation
65+
- nom de l'environnement
66+
- nom du proxy
67+
- numéro de la révision
68+
- nom de la target
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{
3+
"name": "gcp-token-oauth-cache",
4+
"description": "Cache For GCP OAuth SharedFlow",
5+
"expirySettings": {
6+
"timeoutInSec": {
7+
"value": "10"
8+
},
9+
"valuesNull": false
10+
}
11+
}
12+
]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{
3+
"name": "gcp-token-oauth-cache",
4+
"description": "Cache For GCP OAuth SharedFlow",
5+
"expirySettings": {
6+
"timeoutInSec": {
7+
"value": "3500"
8+
},
9+
"valuesNull": false
10+
}
11+
}
12+
]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{
3+
"name": "gcp-token-oauth-cache",
4+
"description": "Cache For GCP OAuth SharedFlow",
5+
"expirySettings": {
6+
"timeoutInSec": {
7+
"value": "60"
8+
},
9+
"valuesNull": false
10+
}
11+
}
12+
]

sharedflows/gcp-token-iap/pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<parent>
4+
<groupId>com.apigee.sharedflows</groupId>
5+
<artifactId>apigee-sharedflow-parent</artifactId>
6+
<version>1.0</version>
7+
<relativePath>../sharedflow-shared-pom.xml</relativePath>
8+
</parent>
9+
10+
<modelVersion>4.0.0</modelVersion>
11+
<groupId>com.apigee.sharedflows</groupId>
12+
<artifactId>apigee-sharedflow-gcp-token-oauth</artifactId>
13+
<name>gcp-token-oauth</name>
14+
<version>1.0</version>
15+
<packaging>pom</packaging>
16+
</project>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<SharedFlowBundle revision="1" name="gcp-token-oauth">
3+
<ConfigurationVersion majorVersion="4" minorVersion="0"/>
4+
<Description>Shared flow permettant de récupérer un token OAuth2 pour appeler un backend GCP</Description>
5+
<DisplayName>gcp-token-oauth</DisplayName>
6+
<Policies>
7+
<Policy>am.create-oauth-header</Policy>
8+
<Policy>ev.extract-json</Policy>
9+
<Policy>gjwt.generate-JWT</Policy>
10+
<Policy>js.extract-credentials</Policy>
11+
<Policy>kvm.gcp-service-account</Policy>
12+
<Policy>lc.gcp-token</Policy>
13+
<Policy>pc.gcp-token</Policy>
14+
<Policy>sc.gcp-oauth</Policy>
15+
</Policies>
16+
<Resources/>
17+
<Spec></Spec>
18+
<subType>SharedFlow</subType>
19+
<SharedFlows>
20+
<SharedFlow>default</SharedFlow>
21+
</SharedFlows>
22+
</SharedFlowBundle>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<AssignMessage async="false" continueOnError="false" enabled="true" name="am.add-authorization">
3+
<DisplayName>am.add-authorization</DisplayName>
4+
<Add>
5+
<Headers>
6+
<Header name="Authorization">Bearer {google-credentials.id-token}</Header>
7+
</Headers>
8+
</Add>
9+
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
10+
</AssignMessage>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<ExtractVariables async="false" continueOnError="false" enabled="true" name="ev.extract-json">
3+
<DisplayName>ev.extract-json</DisplayName>
4+
<JSONPayload>
5+
<Variable name="id-token">
6+
<JSONPath>$.id_token</JSONPath>
7+
</Variable>
8+
</JSONPayload>
9+
<Source clearPayload="false">callout-token</Source>
10+
<VariablePrefix>google-credentials</VariablePrefix>
11+
</ExtractVariables>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<GenerateJWT async="false" continueOnError="false" enabled="true" name="gjwt.generate-JWT">
3+
<Algorithm>RS256</Algorithm>
4+
<PrivateKey>
5+
<Value ref="private.private_key"/>
6+
</PrivateKey>
7+
<Issuer ref="private.client_email"/>
8+
<Audience ref="private.token_uri"/>
9+
<ExpiresIn>300s</ExpiresIn>
10+
<AdditionalClaims>
11+
<Claim name="scope" type="string" ref="private.iap-id" />
12+
</AdditionalClaims>
13+
<OutputVariable>output_jwt</OutputVariable>
14+
</GenerateJWT>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<Javascript async="false" continueOnError="false" enabled="true" timeLimit="200" name="js.extract-credentials">
3+
<DisplayName>js.extract-credentials</DisplayName>
4+
<Properties/>
5+
<Source>
6+
var c = context.getVariable('private.credentialsjson');
7+
c = JSON.parse(c);
8+
for (var prop in c) {
9+
context.setVariable('private.' + prop, c[prop]);
10+
}
11+
</Source>
12+
</Javascript>

0 commit comments

Comments
 (0)