Skip to content

Commit 473abdc

Browse files
authored
feat: introduce new hybrid persistence mapping (#250)
* feat: introduce new hybrid persistence mapping * build: update jans-pycloudlib version
1 parent 759e3db commit 473abdc

File tree

10 files changed

+148
-58
lines changed

10 files changed

+148
-58
lines changed

docker-admin-ui/Dockerfile

+23-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ RUN python3 -m ensurepip \
3535
# jans-linux-setup sync
3636
# =====================
3737

38-
ENV JANS_LINUX_SETUP_VERSION=eb113d09421b95671fe1ab4eaa5c4bafc2aed6af
38+
ENV JANS_LINUX_SETUP_VERSION=afc539d63a70cda21e990fecd470224a4f94e9d6
3939
ARG JANS_SETUP_DIR=jans-linux-setup/jans_setup
4040

4141
# note that as we're pulling from a monorepo (with multiple project in it)
@@ -65,7 +65,7 @@ RUN cd /tmp/jans \
6565
# TODO:
6666
# - use NODE_ENV=production
6767
# - download build package (not git clone)
68-
ENV ADMIN_UI_VERSION=e042a9de63fba051535782b242f38843d39f5afd
68+
ENV ADMIN_UI_VERSION=9de53ada7bd2ca576e8b64b09fa51b002223e84e
6969

7070
# note that as we're pulling from a monorepo (with multiple project in it)
7171
# we are using partial-clone and sparse-checkout to get the admin-ui code
@@ -140,6 +140,27 @@ ENV CN_SECRET_ADAPTER=vault \
140140
CN_SECRET_GOOGLE_SECRET_VERSION_ID=latest \
141141
CN_SECRET_GOOGLE_SECRET_NAME_PREFIX=jans
142142

143+
# ===============
144+
# Persistence ENV
145+
# ===============
146+
147+
ENV CN_PERSISTENCE_TYPE=ldap \
148+
CN_HYBRID_MAPPING="{}" \
149+
CN_LDAP_URL=localhost:1636 \
150+
CN_LDAP_USE_SSL=true \
151+
CN_COUCHBASE_URL=localhost \
152+
CN_COUCHBASE_USER=admin \
153+
CN_COUCHBASE_CERT_FILE=/etc/certs/couchbase.crt \
154+
CN_COUCHBASE_CONN_TIMEOUT=10000 \
155+
CN_COUCHBASE_CONN_MAX_WAIT=20000 \
156+
CN_COUCHBASE_SCAN_CONSISTENCY=not_bounded \
157+
CN_COUCHBASE_BUCKET_PREFIX=jans \
158+
CN_COUCHBASE_TRUSTSTORE_ENABLE=true \
159+
CN_COUCHBASE_KEEPALIVE_INTERVAL=30000 \
160+
CN_COUCHBASE_KEEPALIVE_TIMEOUT=2500 \
161+
CN_GOOGLE_SPANNER_INSTANCE_ID="" \
162+
CN_GOOGLE_SPANNER_DATABASE_ID=""
163+
143164
# ===========
144165
# Generic ENV
145166
# ===========

docker-admin-ui/README.md

+60
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,63 @@ The following environment variables are supported by the container:
5353
- `CN_TOKEN_SERVER_USERINFO_ENDPOINT`: User info endpoint at token server (default to `/jans-auth/restv1/userinfo`).
5454
- `CN_TOKEN_SERVER_CLIENT_ID`: Client ID registered at token server.
5555
- `CN_TOKEN_SERVER_CERT_FILE`: Path to token server certificate (default to `/etc/certs/token_server.crt`).
56+
- `CN_PERSISTENCE_TYPE`: Persistence backend being used (one of `ldap`, `couchbase`, or `hybrid`; default to `ldap`).
57+
- `CN_HYBRID_MAPPING`: Specify data mapping for each persistence (default to `"{}"`). Note this environment only takes effect when `CN_PERSISTENCE_TYPE` is set to `hybrid`. See [hybrid mapping](#hybrid-mapping) section for details.
58+
- `CN_LDAP_URL`: Address and port of LDAP server (default to `localhost:1636`).
59+
- `CN_LDAP_USE_SSL`: Whether to use SSL connection to LDAP server (default to `true`).
60+
- `CN_COUCHBASE_URL`: Address of Couchbase server (default to `localhost`).
61+
- `CN_COUCHBASE_USER`: Username of Couchbase server (default to `admin`).
62+
- `CN_COUCHBASE_CERT_FILE`: Couchbase root certificate location (default to `/etc/certs/couchbase.crt`).
63+
- `CN_COUCHBASE_PASSWORD_FILE`: Path to file contains Couchbase password (default to `/etc/jans/conf/couchbase_password`).
64+
- `CN_COUCHBASE_CONN_TIMEOUT`: Connect timeout used when a bucket is opened (default to `10000` milliseconds).
65+
- `CN_COUCHBASE_CONN_MAX_WAIT`: Maximum time to wait before retrying connection (default to `20000` milliseconds).
66+
- `CN_COUCHBASE_SCAN_CONSISTENCY`: Default scan consistency; one of `not_bounded`, `request_plus`, or `statement_plus` (default to `not_bounded`).
67+
- `CN_COUCHBASE_BUCKET_PREFIX`: Prefix for Couchbase buckets (default to `jans`).
68+
- `CN_COUCHBASE_TRUSTSTORE_ENABLE`: Enable truststore for encrypted Couchbase connection (default to `true`).
69+
- `CN_COUCHBASE_KEEPALIVE_INTERVAL`: Keep-alive interval for Couchbase connection (default to `30000` milliseconds).
70+
- `CN_COUCHBASE_KEEPALIVE_TIMEOUT`: Keep-alive timeout for Couchbase connection (default to `2500` milliseconds).
71+
- `CN_SQL_DB_DIALECT`: Dialect name of SQL backend (one of `mysql`, `pgsql`; default to `mysql`).
72+
- `CN_SQL_DB_HOST`: Host of SQL backend (default to `localhost`).
73+
- `CN_SQL_DB_PORT`: Port of SQL backend (default to `3306`).
74+
- `CN_SQL_DB_NAME`: Database name (default to `jans`)
75+
- `CN_SQL_DB_USER`: User name to interact with SQL backend (default to `jans`).
76+
- `CN_GOOGLE_SPANNER_INSTANCE_ID`: Instance ID of Google Spanner (default to empty string).
77+
- `CN_GOOGLE_SPANNER_DATABASE_ID`: Database ID of Google Spanner (default to empty string).
78+
- `GOOGLE_APPLICATION_CREDENTIALS`: Path to Google credentials JSON file (default to `/etc/jans/conf/google-credentials.json`).
79+
- `GOOGLE_PROJECT_ID`: Google Project ID (default to empty string).
80+
- `GOOGLE_PROJECT_ID`: Google Project ID (default to empty string). Used when `CN_CONFIG_ADAPTER` or `CN_SECRET_ADAPTER` set to `google`.
81+
- `GOOGLE_APPLICATION_CREDENTIALS`: Path to Google credentials JSON file (default to `/etc/jans/conf/google-credentials.json`). Used when `CN_CONFIG_ADAPTER` or `CN_SECRET_ADAPTER` set to `google`.
82+
- `CN_GOOGLE_SPANNER_INSTANCE_ID`: Google Spanner instance ID.
83+
- `CN_GOOGLE_SPANNER_DATABASE_ID`: Google Spanner database ID.
84+
85+
### Hybrid mapping
86+
87+
Hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below:
88+
89+
1. Set `CN_PERSISTENCE_TYPE` environment variable to `hybrid`
90+
91+
1. Set `CN_HYBRID_MAPPING` with the following format:
92+
93+
```
94+
{
95+
"default": "<couchbase|ldap|spanner|sql>",
96+
"user": "<couchbase|ldap|spanner|sql>",
97+
"site": "<couchbase|ldap|spanner|sql>",
98+
"cache": "<couchbase|ldap|spanner|sql>",
99+
"token": "<couchbase|ldap|spanner|sql>",
100+
"session": "<couchbase|ldap|spanner|sql>",
101+
}
102+
```
103+
104+
Example:
105+
106+
```
107+
{
108+
"default": "sql",
109+
"user": "spanner",
110+
"site": "ldap",
111+
"cache": "sql",
112+
"token": "couchbase",
113+
"session": "spanner",
114+
}
115+
```

docker-admin-ui/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
libcst<0.4
22
# pinned to py3-grpcio version to avoid failure on native extension build
33
grpcio==1.41.0
4-
git+https://github.com/JanssenProject/jans@f2e653ef917efd017195f2330b64e64c333f4699#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
4+
git+https://github.com/JanssenProject/jans@d9f9cd6bb55a644d60eba7355a5077f159854020#egg=jans-pycloudlib&subdirectory=jans-pycloudlib

docker-admin-ui/scripts/bootstrap.py

+3-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from jans.pycloudlib.persistence import LdapClient
1111
from jans.pycloudlib.persistence import SpannerClient
1212
from jans.pycloudlib.persistence import SqlClient
13+
from jans.pycloudlib.persistence.utils import PersistenceMapper
1314

1415
from settings import LOGGING_CONFIG
1516

@@ -82,16 +83,8 @@ def __init__(self, manager):
8283
}
8384

8485
# determine persistence type
85-
self.persistence_type = os.environ.get("CN_PERSISTENCE_TYPE", "ldap")
86-
ldap_mapping = os.environ.get("CN_PERSISTENCE_LDAP_MAPPING", "default")
87-
88-
if self.persistence_type == "hybrid":
89-
if ldap_mapping == "default":
90-
client_cls = LdapClient
91-
self.persistence_type = "ldap"
92-
else:
93-
client_cls = CouchbaseClient
94-
self.persistence_type = "couchbase"
86+
mapper = PersistenceMapper()
87+
self.persistence_type = mapper.mapping["default"]
9588

9689
# determine persistence client
9790
client_cls = client_classes.get(self.persistence_type)

docker-admin-ui/scripts/wait.py

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,33 @@
1-
import logging
21
import logging.config
32
import os
43

54
from jans.pycloudlib import get_manager
65
from jans.pycloudlib import wait_for
6+
from jans.pycloudlib import wait_for_persistence
77
from jans.pycloudlib.validators import validate_persistence_type
8-
from jans.pycloudlib.validators import validate_persistence_ldap_mapping
8+
from jans.pycloudlib.validators import validate_persistence_hybrid_mapping
99
from jans.pycloudlib.validators import validate_persistence_sql_dialect
1010

1111
from settings import LOGGING_CONFIG
1212

1313
logging.config.dictConfig(LOGGING_CONFIG)
14-
logger = logging.getLogger("wait")
1514

1615

1716
def main():
1817
persistence_type = os.environ.get("CN_PERSISTENCE_TYPE", "ldap")
1918
validate_persistence_type(persistence_type)
2019

21-
ldap_mapping = os.environ.get("CN_PERSISTENCE_LDAP_MAPPING", "default")
22-
validate_persistence_ldap_mapping(persistence_type, ldap_mapping)
20+
if persistence_type == "hybrid":
21+
validate_persistence_hybrid_mapping()
2322

2423
if persistence_type == "sql":
2524
sql_dialect = os.environ.get("CN_SQL_DB_DIALECT", "mysql")
2625
validate_persistence_sql_dialect(sql_dialect)
2726

2827
manager = get_manager()
2928
deps = ["config", "secret"]
30-
31-
if persistence_type == "hybrid":
32-
deps += ["ldap", "couchbase"]
33-
else:
34-
deps.append(persistence_type)
35-
3629
wait_for(manager, deps)
30+
wait_for_persistence(manager)
3731

3832

3933
if __name__ == "__main__":

docker-casa/Dockerfile

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ EXPOSE 8080
3535
# ====
3636

3737
ENV GLUU_VERSION=5.0.0-SNAPSHOT
38-
ENV GLUU_BUILD_DATE='2022-05-12 11:53'
38+
ENV GLUU_BUILD_DATE='2022-05-26 13:57'
3939
ENV GLUU_SOURCE_URL=https://jenkins.gluu.org/maven/org/gluu/casa/${GLUU_VERSION}/casa-${GLUU_VERSION}.war
4040

4141
# Install Casa
@@ -63,7 +63,7 @@ RUN python3 -m ensurepip \
6363
# jans-linux-setup sync
6464
# =====================
6565

66-
ENV JANS_LINUX_SETUP_VERSION=eb113d09421b95671fe1ab4eaa5c4bafc2aed6af
66+
ENV JANS_LINUX_SETUP_VERSION=afc539d63a70cda21e990fecd470224a4f94e9d6
6767
ARG JANS_SETUP_DIR=jans-linux-setup/jans_setup
6868

6969
# note that as we're pulling from a monorepo (with multiple project in it)
@@ -90,7 +90,7 @@ RUN cd /tmp/jans \
9090
# flex setup sync
9191
# ===============
9292

93-
ENV FLEX_VERSION=e042a9de63fba051535782b242f38843d39f5afd
93+
ENV FLEX_VERSION=9de53ada7bd2ca576e8b64b09fa51b002223e84e
9494
ARG FLEX_SETUP_DIR=flex-linux-setup/flex_linux_setup
9595
ARG CASA_EXTRAS_DIR=casa/extras
9696

@@ -168,7 +168,7 @@ ENV CN_SECRET_ADAPTER=vault \
168168
# ===============
169169

170170
ENV CN_PERSISTENCE_TYPE=ldap \
171-
CN_PERSISTENCE_LDAP_MAPPING=default \
171+
CN_HYBRID_MAPPING="{}" \
172172
CN_LDAP_URL=localhost:1636 \
173173
CN_LDAP_USE_SSL=true \
174174
CN_COUCHBASE_URL=localhost \

docker-casa/README.md

+33-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The following environment variables are supported by the container:
4141
- `CN_WAIT_SLEEP_DURATION`: Delay between startup "health checks" (default to `10` seconds).
4242
- `CN_MAX_RAM_PERCENTAGE`: Value passed to Java option `-XX:MaxRAMPercentage`.
4343
- `CN_PERSISTENCE_TYPE`: Persistence backend being used (one of `ldap`, `couchbase`, or `hybrid`; default to `ldap`).
44-
- `CN_PERSISTENCE_LDAP_MAPPING`: Specify data that should be saved in LDAP (one of `default`, `user`, `cache`, `site`, `token`, or `session`; default to `default`). Note this environment only takes effect when `CN_PERSISTENCE_TYPE` is set to `hybrid`.
44+
- `CN_HYBRID_MAPPING`: Specify data mapping for each persistence (default to `"{}"`). Note this environment only takes effect when `CN_PERSISTENCE_TYPE` is set to `hybrid`. See [hybrid mapping](#hybrid-mapping) section for details.
4545
- `CN_LDAP_URL`: Address and port of LDAP server (default to `localhost:1636`); required if `CN_PERSISTENCE_TYPE` is set to `ldap` or `hybrid`.
4646
- `CN_LDAP_USE_SSL`: Whether to use SSL connection to LDAP server (default to `true`).
4747
- `CN_COUCHBASE_URL`: Address of Couchbase server (default to `localhost`); required if `CN_PERSISTENCE_TYPE` is set to `couchbase` or `hybrid`.
@@ -102,3 +102,35 @@ The following key-value pairs are the defaults:
102102
"timer_log_level": "INFO"
103103
}
104104
```
105+
106+
### Hybrid mapping
107+
108+
Hybrid persistence supports all available persistence types. To configure hybrid persistence and its data mapping, follow steps below:
109+
110+
1. Set `CN_PERSISTENCE_TYPE` environment variable to `hybrid`
111+
112+
1. Set `CN_HYBRID_MAPPING` with the following format:
113+
114+
```
115+
{
116+
"default": "<couchbase|ldap|spanner|sql>",
117+
"user": "<couchbase|ldap|spanner|sql>",
118+
"site": "<couchbase|ldap|spanner|sql>",
119+
"cache": "<couchbase|ldap|spanner|sql>",
120+
"token": "<couchbase|ldap|spanner|sql>",
121+
"session": "<couchbase|ldap|spanner|sql>",
122+
}
123+
```
124+
125+
Example:
126+
127+
```
128+
{
129+
"default": "sql",
130+
"user": "spanner",
131+
"site": "ldap",
132+
"cache": "sql",
133+
"token": "couchbase",
134+
"session": "spanner",
135+
}
136+
```

docker-casa/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ webdavclient3>=3.14.5
22
libcst<0.4
33
# pinned to py3-grpcio version to avoid failure on native extension build
44
grpcio==1.41.0
5-
git+https://github.com/JanssenProject/jans@f2e653ef917efd017195f2330b64e64c333f4699#egg=jans-pycloudlib&subdirectory=jans-pycloudlib
5+
git+https://github.com/JanssenProject/jans@d9f9cd6bb55a644d60eba7355a5077f159854020#egg=jans-pycloudlib&subdirectory=jans-pycloudlib

docker-casa/scripts/bootstrap.py

+13-17
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from jans.pycloudlib.persistence import SqlClient
2424
from jans.pycloudlib.persistence import doc_id_from_dn
2525
from jans.pycloudlib.persistence import id_from_dn
26+
from jans.pycloudlib.persistence.utils import PersistenceMapper
2627
from jans.pycloudlib.utils import cert_to_truststore
2728
from jans.pycloudlib.utils import get_random_chars
2829
from jans.pycloudlib.utils import encode_text
@@ -141,33 +142,36 @@ def main():
141142
render_salt(manager, "/app/templates/salt.tmpl", "/etc/jans/conf/salt")
142143
render_base_properties("/app/templates/jans.properties.tmpl", "/etc/jans/conf/jans.properties")
143144

144-
if persistence_type in ("ldap", "hybrid"):
145+
mapper = PersistenceMapper()
146+
persistence_groups = mapper.groups()
147+
148+
if persistence_type == "hybrid":
149+
render_hybrid_properties("/etc/jans/conf/jans-hybrid.properties")
150+
151+
if "ldap" in persistence_groups:
145152
render_ldap_properties(
146153
manager,
147154
"/app/templates/jans-ldap.properties.tmpl",
148155
"/etc/jans/conf/jans-ldap.properties",
149156
)
150157
sync_ldap_truststore(manager)
151158

152-
if persistence_type in ("couchbase", "hybrid"):
159+
if "couchbase" in persistence_groups:
153160
render_couchbase_properties(
154161
manager,
155162
"/app/templates/jans-couchbase.properties.tmpl",
156163
"/etc/jans/conf/jans-couchbase.properties",
157164
)
158165
sync_couchbase_truststore(manager)
159166

160-
if persistence_type == "hybrid":
161-
render_hybrid_properties("/etc/jans/conf/jans-hybrid.properties")
162-
163-
if persistence_type == "sql":
167+
if "sql" in persistence_groups:
164168
render_sql_properties(
165169
manager,
166170
"/app/templates/jans-sql.properties.tmpl",
167171
"/etc/jans/conf/jans-sql.properties",
168172
)
169173

170-
if persistence_type == "spanner":
174+
if "spanner" in persistence_groups:
171175
render_spanner_properties(
172176
manager,
173177
"/app/templates/jans-spanner.properties.tmpl",
@@ -204,16 +208,8 @@ def __init__(self, manager):
204208
}
205209

206210
# determine persistence type
207-
self.persistence_type = os.environ.get("CN_PERSISTENCE_TYPE", "ldap")
208-
ldap_mapping = os.environ.get("CN_PERSISTENCE_LDAP_MAPPING", "default")
209-
210-
if self.persistence_type == "hybrid":
211-
if ldap_mapping == "default":
212-
client_cls = LdapClient
213-
self.persistence_type = "ldap"
214-
else:
215-
client_cls = CouchbaseClient
216-
self.persistence_type = "couchbase"
211+
mapper = PersistenceMapper()
212+
self.persistence_type = mapper.mapping["default"]
217213

218214
# determine persistence client
219215
client_cls = client_classes.get(self.persistence_type)

docker-casa/scripts/wait.py

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,33 @@
1-
import logging
21
import logging.config
32
import os
43

54
from jans.pycloudlib import get_manager
65
from jans.pycloudlib import wait_for
6+
from jans.pycloudlib import wait_for_persistence
77
from jans.pycloudlib.validators import validate_persistence_type
8-
from jans.pycloudlib.validators import validate_persistence_ldap_mapping
8+
from jans.pycloudlib.validators import validate_persistence_hybrid_mapping
99
from jans.pycloudlib.validators import validate_persistence_sql_dialect
1010

1111
from settings import LOGGING_CONFIG
1212

1313
logging.config.dictConfig(LOGGING_CONFIG)
14-
logger = logging.getLogger("wait")
1514

1615

1716
def main():
1817
persistence_type = os.environ.get("CN_PERSISTENCE_TYPE", "ldap")
1918
validate_persistence_type(persistence_type)
2019

21-
ldap_mapping = os.environ.get("CN_PERSISTENCE_LDAP_MAPPING", "default")
22-
validate_persistence_ldap_mapping(persistence_type, ldap_mapping)
20+
if persistence_type == "hybrid":
21+
validate_persistence_hybrid_mapping()
2322

2423
if persistence_type == "sql":
2524
sql_dialect = os.environ.get("CN_SQL_DB_DIALECT", "mysql")
2625
validate_persistence_sql_dialect(sql_dialect)
2726

2827
manager = get_manager()
2928
deps = ["config", "secret"]
30-
31-
if persistence_type == "hybrid":
32-
deps += ["ldap", "couchbase"]
33-
else:
34-
deps.append(persistence_type)
35-
3629
wait_for(manager, deps)
30+
wait_for_persistence(manager)
3731

3832

3933
if __name__ == "__main__":

0 commit comments

Comments
 (0)