Codebase list libapache2-mod-auth-openidc / ba321ca
New upstream version 2.4.11.1 Moritz Schlarb 2 years ago
26 changed file(s) with 692 addition(s) and 873 deletion(s). Raw diff Collapse all Expand all
0 /Dockerfile*
0 /Dockerfile*
1 /.cproject
2 /.project
3 /*.la
4 /*.log
5 /*.rpm
6 /configure
7 /configure~
8 /config.guess*
9 /config.status
10 /config.sub*
11 /depcomp
12 /ar-lib
13 /aclocal.m4
14 /.gitignore
15 /test/Dockerfile
16 /test/*.la
17 /test/*.log
18 /test/.gitignore
19 /test/openidc.conf
20 /test/keycloak.sh
21 /test/jmeter.sh
22 /test/valgrind.sh
23 /test/mod_auth_openidc.jmx
24 /.github
25 /test/docker-compose.yml
26 /test/docker-compose-mac.yml
0 name: Valgrind
1
2 on:
3 push:
4 branches: [ master ]
5
6 jobs:
7 valgrind:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v2
11 - name: Run
12 run: |
13 pip3 install docker-compose --upgrade
14 docker-compose -f test/docker-compose.yml up --build --abort-on-container-exit
8080 sebastian-goeldi <https://github.com/sebastian-goeldi>
8181 rajeevn1 <https://github.com/rajeevn1>
8282 Daan Bakker <https://github.com/dbakker>
83 smanolache <https://github.com/smanolache>
0 03/29/2022
1 - release 2.4.11.1
2
3 03/28/2022
4 - correct registration_endpoint_json naming in auth_openidc.conf documentation
5
6 03/21/2022
7 - fix OIDCUnAuthAction pass, see #790
8 - bump to 2.4.11.1rc5
9
10 03/18/2022
11 - fix make check; add @smanolache to the AUTHORS file
12 - bump to 2.4.11.1rc4
13
14 03/17/2022
15 - fix memory leaks over graceful restarts: use s->process->pconf pool instead of
16 the s->process->pool in oidc_slog and oidc_cache_shm_cfg_create
17 closes #823 and #824; thanks @smanolache
18
19 03/14/2022
20 - fix temporary cache file naming; see #777
21
22 03/08/2022
23 - fix a 2nd race condition in the file cache backend; see #777; thanks @dbakker and @blackwhiser1
24 - bump to 2.4.11.1rc3
25
26 03/04/2022
27 - add support for OpenSSL 3.0
28 - remove test-cmd jwk2cert command
29 - bump to 2.4.11.1rc2
30
31 02/28/2022
32 - add a check to make sure URLs do not contain unencoded Unicode characters; see #796; thanks @cnico
33 - bump to 2.4.11.1rc1
34
35 02/27/2022
36 - document Apache 2.4 behavior on OIDCUnAuthzAction 403; see #795; thanks @candlerb
37
38 02/04/2022
39 - correct ap_hook_insert_filter function signature in stub.c, part 2; closes #784; thanks @stroeder
40
41 02/03/2022
42 - add Valgrind Github action
43 - warn about mismatch between incoming X-Forwarded-* headers and OIDCXForwardedHeaders configuration
44 - avoid using %llu print formatter and switch to %lu for unsigned long so it works cross platform
45 - bump to 2.4.11.1rc0
46
047 01/26/2022
148 - improve handling session duration expiry when combined with OIDCUnAuthAction or Discovery
249 also clear r->user in oidc_session_kill for such cases; see #778
110110 # This settings serves as a default value for multiple OPs only.
111111 # Parameter names and values need to be provided in JSON form and will be merged in to the request.
112112 # When not defined no extra parameters will be passed.
113 # NB: this can be overridden on a per-OP basis in the .conf file using the key: registration_endpoint_params
113 # NB: this can be overridden on a per-OP basis in the .conf file using the key: registration_endpoint_json
114114 #OIDCProviderRegistrationEndpointJson <json-string>
115115
116116 # Define the OpenID Connect scope that is requested from the OP (eg. "openid email profile").
858858 # "302" redirect to the URL specified in the <argument> parameter
859859 # "auth" redirect the user to the OpenID Connect Provider or Discovery page for authentication (<argument> is unused)
860860 # Useful in Location/Directory/Proxy path contexts that need to do stepup authentication
861 # When not defined the default "401" is used.
861 # When not defined the default "403" is used. However Apache 2.4 will change this to 401
862 # unless you set "AuthzSendForbiddenOnFailure on"
862863 #OIDCUnAutzAction [401|403|302|auth] [<argument>]
863864
864865 # Indicates whether POST data will be preserved across authentication requests (and discovery in case of multiple OPs).
0 AC_INIT([mod_auth_openidc],[2.4.11],[hans.zandbelt@zmartzone.eu])
0 AC_INIT([mod_auth_openidc],[2.4.11.1],[hans.zandbelt@zmartzone.eu])
11
22 AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
33
373373 /*
374374 * write a value for the specified key to the cache
375375 */
376 static apr_byte_t oidc_cache_file_set(request_rec *r, const char *section,
377 const char *key, const char *value, apr_time_t expiry) {
376 static apr_byte_t oidc_cache_file_set(request_rec *r, const char *section, const char *key,
377 const char *value, apr_time_t expiry) {
378378 apr_file_t *fd = NULL;
379379 apr_status_t rc = APR_SUCCESS;
380380 char s_err[128];
381 char *rnd = NULL;
382
383 oidc_proto_generate_nonce(r, &rnd, 12);
381384
382385 /* get the fully qualified path to the cache file based on the key name */
383 const char *path = oidc_cache_file_path(r, section, key);
386 const char *target = oidc_cache_file_path(r, section, key);
387 const char *path = apr_psprintf(r->pool, "%s.%s.tmp", target, rnd);
384388
385389 /* only on writes (not on reads) we clean the cache first (if not done recently) */
386390 oidc_cache_file_clean(r);
388392 /* just remove cache file if value is NULL */
389393 if (value == NULL) {
390394 if ((rc = apr_file_remove(path, r->pool)) != APR_SUCCESS) {
391 oidc_error(r, "could not delete cache file \"%s\" (%s)", path,
392 apr_strerror(rc, s_err, sizeof(s_err)));
395 oidc_error(r, "could not delete cache file \"%s\" (%s)", path, apr_strerror(rc, s_err, sizeof(s_err)));
393396 }
394397 return TRUE;
395398 }
396399
397400 /* try to open the cache file for writing, creating it if it does not exist */
398 if ((rc = apr_file_open(&fd, path,
399 (APR_FOPEN_WRITE | APR_FOPEN_CREATE),
400 APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
401 oidc_error(r, "cache file \"%s\" could not be opened (%s)", path,
402 apr_strerror(rc, s_err, sizeof(s_err)));
401 if ((rc = apr_file_open(&fd, path, (APR_FOPEN_WRITE | APR_FOPEN_CREATE),
402 APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
403 oidc_error(r, "cache file \"%s\" could not be opened (%s)", path, apr_strerror(rc, s_err, sizeof(s_err)));
403404 return FALSE;
404405 }
405406
415416 info.len = strlen(value) + 1;
416417
417418 /* write the header */
418 if ((rc = oidc_cache_file_write(r, path, fd, &info,
419 sizeof(oidc_cache_file_info_t))) != APR_SUCCESS)
419 if ((rc = oidc_cache_file_write(r, path, fd, &info, sizeof(oidc_cache_file_info_t)))
420 != APR_SUCCESS)
420421 return FALSE;
421422
422423 /* next write the value */
423 rc = oidc_cache_file_write(r, path, fd, (void *) value, info.len);
424 rc = oidc_cache_file_write(r, path, fd, (void*) value, info.len);
424425
425426 /* unlock and close the written file */
426427 apr_file_unlock(fd);
427428 apr_file_close(fd);
428429
430 if (rename(path, target) != 0) {
431 oidc_error(r, "cache file: %s could not be renamed to: %s", path, target);
432 return FALSE;
433 }
434
429435 /* log our success/failure */
430 oidc_debug(r,
431 "%s entry for key \"%s\" in file of %" APR_SIZE_T_FMT " bytes",
432 (rc == APR_SUCCESS) ? "successfully stored" : "could not store",
433 key, info.len);
436 oidc_debug(r, "%s entry for key \"%s\" in file of %" APR_SIZE_T_FMT " bytes", (rc == APR_SUCCESS) ? "successfully stored" : "could not store", key, info.len);
434437
435438 return (rc == APR_SUCCESS);
436439 }
8989
9090 if (cfg->cache_cfg != NULL)
9191 return APR_SUCCESS;
92 oidc_cache_cfg_shm_t *context = oidc_cache_shm_cfg_create(s->process->pool);
92 oidc_cache_cfg_shm_t *context = oidc_cache_shm_cfg_create(s->process->pconf);
9393 cfg->cache_cfg = context;
9494
9595 /* create the shared memory segment */
9696 apr_status_t rv = apr_shm_create(&context->shm,
9797 (apr_size_t) cfg->cache_shm_entry_size_max
9898 * cfg->cache_shm_size_max,
99 NULL, s->process->pool);
99 NULL, s->process->pconf);
100100 if (rv != APR_SUCCESS) {
101101 oidc_serror(s, "apr_shm_create failed to create shared memory segment");
102102 return HTTP_INTERNAL_SERVER_ERROR;
237237 > (cfg->cache_shm_entry_size_max
238238 - sizeof(oidc_cache_shm_entry_t)))) {
239239 oidc_error(r,
240 "could not store value since value size is too large (%llu > %lu); consider increasing " OIDCCacheShmEntrySizeMax "",
241 (unsigned long long )strlen(value),
240 "could not store value since value size is too large (%lu > %lu); consider increasing " OIDCCacheShmEntrySizeMax "",
241 (unsigned long )strlen(value),
242242 (unsigned long )(cfg->cache_shm_entry_size_max
243243 - sizeof(oidc_cache_shm_entry_t)));
244244 return FALSE;
12401240 return OIDC_CONFIG_DIR_RV(cmd, rv);
12411241 }
12421242
1243 static void oidc_check_x_forwarded_hdr(request_rec *r, const apr_byte_t x_forwarded_headers,
1244 const apr_byte_t hdr_type, const char *hdr_str,
1245 const char* (hdr_func)(const request_rec *r)) {
1246 if (hdr_func(r)) {
1247 if (!(x_forwarded_headers & hdr_type))
1248 oidc_warn(r, "header %s received but %s not configured for it", hdr_str, OIDCXForwardedHeaders);
1249 } else {
1250 if (x_forwarded_headers & hdr_type)
1251 oidc_warn(r, "%s configured for header %s but not found in request", OIDCXForwardedHeaders, hdr_str);
1252 }
1253 }
1254
1255 void oidc_config_check_x_forwarded(request_rec *r, const apr_byte_t x_forwarded_headers) {
1256 oidc_check_x_forwarded_hdr(r, x_forwarded_headers, OIDC_HDR_X_FORWARDED_HOST, OIDC_HTTP_HDR_X_FORWARDED_HOST, oidc_util_hdr_in_x_forwarded_host_get);
1257 oidc_check_x_forwarded_hdr(r, x_forwarded_headers, OIDC_HDR_X_FORWARDED_PORT, OIDC_HTTP_HDR_X_FORWARDED_PORT, oidc_util_hdr_in_x_forwarded_port_get);
1258 oidc_check_x_forwarded_hdr(r, x_forwarded_headers, OIDC_HDR_X_FORWARDED_PROTO, OIDC_HTTP_HDR_X_FORWARDED_PROTO, oidc_util_hdr_in_x_forwarded_proto_get);
1259 }
1260
12431261 static const char* oidc_set_redirect_urls_allowed(cmd_parms *cmd, void *m,
12441262 const char *arg) {
12451263 oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
5353 #include <openssl/pem.h>
5454 #include <openssl/rsa.h>
5555 #include <openssl/bn.h>
56 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
57 #include <openssl/core_names.h>
58 #endif
5659
5760 #ifdef WIN32
5861 #define snprintf _snprintf
12471250 }
12481251 }
12491252
1253 BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
1254
1255 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1256 EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n);
1257 EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e);
1258 EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_D, &rsa_d);
1259 #else
12501260 /* get the RSA key from the public key struct */
12511261 RSA *rsa = (RSA *)EVP_PKEY_get1_RSA(pkey);
12521262 if (rsa == NULL) {
12541264 goto end;
12551265 }
12561266
1257 const BIGNUM *rsa_n, *rsa_e, *rsa_d;
1258 #if OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined (LIBRESSL_VERSION_NUMBER)
1259 RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
1267 #if OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined(LIBRESSL_VERSION_NUMBER)
1268 RSA_get0_key(rsa, (const BIGNUM **)&rsa_n, (const BIGNUM **)&rsa_e, (const BIGNUM **)&rsa_d);
12601269 #else
12611270 rsa_n = rsa->n;
12621271 rsa_e = rsa->e;
12641273 #endif
12651274
12661275 RSA_free(rsa);
1276 #endif
12671277
12681278 /* convert the modulus bignum in to a key/len */
12691279 key_spec.nlen = BN_num_bytes(rsa_n);
4444
4545 #ifndef MOD_AUTH_OPENIDC_JOSE_H_
4646 #define MOD_AUTH_OPENIDC_JOSE_H_
47
48 #define OPENSSL_API_COMPAT 0x10000000L
49 #define OPENSSL_NO_DEPRECATED 1
5047
5148 #include <stdint.h>
5249 #include "apr_pools.h"
22952295 /* create the state between request/response */
22962296 oidc_proto_state_t *proto_state = oidc_proto_state_new();
22972297 oidc_proto_state_set_original_url(proto_state, original_url);
2298
2299 if (oidc_proto_state_get_original_url(proto_state) == NULL) {
2300 oidc_error(r, "could not store the current URL in the state: most probably you need to ensure that it does not contain unencoded Unicode characters e.g. by forcing IE 11 to encode all URL characters");
2301 return HTTP_INTERNAL_SERVER_ERROR;
2302 }
2303
22982304 oidc_proto_state_set_original_method(proto_state,
22992305 oidc_original_request_method(r, c, TRUE));
23002306 oidc_proto_state_set_issuer(proto_state, provider->issuer);
40194025
40204026 /* see if we've configured OIDCUnAutzAction for this path */
40214027 switch (oidc_dir_cfg_unautz_action(r)) {
4022 // TODO: document that AuthzSendForbiddenOnFailure is required to return 403 FORBIDDEN
40234028 case OIDC_UNAUTZ_RETURN403:
40244029 case OIDC_UNAUTZ_RETURN401:
40254030 if (oidc_dir_cfg_unauthz_arg(r)) {
40834088 oidc_debug(r, "enter: (r->user=%s) require_args=\"%s\"", r->user, require_args);
40844089
40854090 /* check for anonymous access and PASS mode */
4086 if ((r->user != NULL) && (strlen(r->user) == 0))
4091 if ((r->user != NULL) && (strlen(r->user) == 0)) {
40874092 r->user = NULL;
4088
4089 if (oidc_dir_cfg_unauth_action(r) == OIDC_UNAUTH_PASS)
4090 return AUTHZ_GRANTED;
4091 if (oidc_request_state_get(r, OIDC_REQUEST_STATE_KEY_DISCOVERY) != NULL)
4092 return AUTHZ_GRANTED;
4093 if (r->method_number == M_OPTIONS)
4094 return AUTHZ_GRANTED;
4093 if (oidc_dir_cfg_unauth_action(r) == OIDC_UNAUTH_PASS)
4094 return AUTHZ_GRANTED;
4095 if (oidc_request_state_get(r, OIDC_REQUEST_STATE_KEY_DISCOVERY) != NULL)
4096 return AUTHZ_GRANTED;
4097 if (r->method_number == M_OPTIONS)
4098 return AUTHZ_GRANTED;
4099 }
40954100
40964101 /* get the set of claims from the request state (they've been set in the authentication part earlier */
40974102 json_t *claims = NULL, *id_token = NULL;
41804185 int oidc_auth_checker(request_rec *r) {
41814186
41824187 /* check for anonymous access and PASS mode */
4183 if ((r->user != NULL) && (strlen(r->user) == 0))
4188 if ((r->user != NULL) && (strlen(r->user) == 0)) {
41844189 r->user = NULL;
4185
4186 if (oidc_dir_cfg_unauth_action(r) == OIDC_UNAUTH_PASS)
4187 return OK;
4188 if (oidc_request_state_get(r, OIDC_REQUEST_STATE_KEY_DISCOVERY) != NULL)
4189 return OK;
4190 if (r->method_number == M_OPTIONS)
4191 return OK;
4190 if (oidc_dir_cfg_unauth_action(r) == OIDC_UNAUTH_PASS)
4191 return OK;
4192 if (oidc_request_state_get(r, OIDC_REQUEST_STATE_KEY_DISCOVERY) != NULL)
4193 return OK;
4194 if (r->method_number == M_OPTIONS)
4195 return OK;
4196 }
41924197
41934198 /* get the set of claims from the request state (they've been set in the authentication part earlier */
41944199 json_t *claims = NULL, *id_token = NULL;
7979 #endif
8080
8181 #define oidc_log(r, level, fmt, ...) ap_log_rerror(APLOG_MARK, level, 0, r,"%s: %s", __FUNCTION__, apr_psprintf(r->pool, fmt, ##__VA_ARGS__))
82 #define oidc_slog(s, level, fmt, ...) ap_log_error(APLOG_MARK, level, 0, s, "%s: %s", __FUNCTION__, apr_psprintf(s->process->pool, fmt, ##__VA_ARGS__))
82 #define oidc_slog(s, level, fmt, ...) ap_log_error(APLOG_MARK, level, 0, s, "%s: %s", __FUNCTION__, apr_psprintf(s->process->pconf, fmt, ##__VA_ARGS__))
8383 //#define oidc_log(r, level, fmt, ...) fprintf(stderr, "# %s: %s\n", __FUNCTION__, apr_psprintf(r->pool, fmt, ##__VA_ARGS__))
8484 //#define oidc_slog(s, level, fmt, ...) fprintf(stderr, "## %s: %s\n", __FUNCTION__, apr_psprintf(s->process->pool, fmt, ##__VA_ARGS__))
8585
762762 char *oidc_cfg_dir_state_cookie_prefix(request_rec *r);
763763 int oidc_cfg_delete_oldest_state_cookies(oidc_cfg *cfg);
764764 void oidc_cfg_provider_init(oidc_provider_t *provider);
765 void oidc_config_check_x_forwarded(request_rec *r, const apr_byte_t x_forwarded_headers);
765766
766767 // oidc_util.c
767768 int oidc_strnenvcmp(const char *a, const char *b, int len);
590590 */
591591 static const char* oidc_get_current_url_base(request_rec *r, const apr_byte_t x_forwarded_headers) {
592592
593 const char *scheme_str = oidc_get_current_url_scheme(r, x_forwarded_headers);
594 const char *host_str = oidc_get_current_url_host(r, x_forwarded_headers);
595 const char *port_str = oidc_get_current_url_port(r, scheme_str, x_forwarded_headers);
593 const char *scheme_str = NULL;
594 const char *host_str = NULL;
595 const char *port_str = NULL;
596
597 oidc_config_check_x_forwarded(r, x_forwarded_headers);
598
599 scheme_str = oidc_get_current_url_scheme(r, x_forwarded_headers);
600 host_str = oidc_get_current_url_host(r, x_forwarded_headers);
601 port_str = oidc_get_current_url_port(r, scheme_str, x_forwarded_headers);
596602 port_str = port_str ? apr_psprintf(r->pool, ":%s", port_str) : "";
597603
598604 char *url = apr_pstrcat(r->pool, scheme_str, "://", host_str, port_str,
20532059
20542060 /* some logging about what we're going to do */
20552061 oidc_debug(r,
2056 "parsing attribute array for key \"%s\" (#nr-of-elems: %llu)",
2057 s_key, (unsigned long long )json_array_size(j_value));
2062 "parsing attribute array for key \"%s\" (#nr-of-elems: %lu)",
2063 s_key, (unsigned long)json_array_size(j_value));
20582064
20592065 /* string to hold the concatenated array string values */
20602066 char *s_concat = apr_pstrdup(r->pool, "");
55 /*.slo
66 /.libs/
77 /test-cmd
8 /*.json
98 /*.jwt
109 /*.jwk
1110 /jmx/
0 FROM ubuntu:focal
1
2 ENV DEBIAN_FRONTEND noninteractive
3
4 RUN apt-get update && apt-get install -y \
5 pkg-config autoconf automake libtool \
6 make gcc gdb lcov \
7 valgrind apache2 check \
8 libssl-dev libjansson-dev libcurl4-openssl-dev \
9 apache2-dev libpcre2-dev \
10 libcjose-dev libhiredis-dev \
11 vim curl iputils-ping wget
12
13 RUN a2enmod ssl proxy proxy_http && \
14 a2ensite default-ssl
15
16 COPY . mod_auth_openidc
17
18 RUN cd mod_auth_openidc && ./autogen.sh && \
19 ./configure CFLAGS="-g -O0" LDFLAGS="-lrt" && \
20 make clean && make check && make install
21
22 RUN /usr/sbin/apache2ctl start
0 version: '3'
1
2 services:
3
4 keycloak:
5 image: sleighzy/keycloak:16.1.0-arm64
6 #build:
7 # context: https://github.com/keycloak/keycloak-containers.git#16.1.1:server
8 ports:
9 - "8443:8443"
10
11 apache:
12 ports:
13 - "443:443"
14
15 jmeter:
16 environment:
17 THREADS: 2
18 LOOP: 2
19
20 # docker-compose -f test/docker-compose.yml -f test/docker-compose-mac.yml up --build --abort-on-container-exit
21 # docker exec -it `docker ps | grep apache | cut -d" " -f1` tail -f /var/log/apache2/error.log
0 version: '3'
1
2 services:
3
4 keycloak:
5 image: jboss/keycloak:16.1.1
6 environment:
7 KEYCLOAK_USER: admin
8 KEYCLOAK_PASSWORD: admin
9 expose:
10 - "8443"
11 volumes:
12 - ./keycloak.sh:/opt/jboss/startup-scripts/keycloak.sh
13
14 echo:
15 image: solsson/http-echo
16 expose:
17 - "80"
18
19 apache:
20 build:
21 context: ..
22 dockerfile: test/Dockerfile
23 expose:
24 - "443"
25 volumes:
26 - ./valgrind.sh:/tmp/valgrind.sh
27 - ./openidc.conf:/etc/apache2/conf-available/openidc.conf
28 command: ["/tmp/valgrind.sh"]
29
30 jmeter:
31 #image: justb4/jmeter
32 build: https://github.com/justb4/docker-jmeter.git
33 entrypoint: ["/tmp/jmeter.sh"]
34 depends_on:
35 - keycloak
36 - echo
37 - apache
38 environment:
39 THREADS: 5
40 LOOP: 5
41 volumes:
42 - ./jmeter.sh:/tmp/jmeter.sh
43 - ./mod_auth_openidc.jmx:/tmp/mod_auth_openidc.jmx
44 - /var/run/docker.sock:/var/run/docker.sock
0 #!/bin/bash
1
2 # install utilities needed for accessing the Docker API
3 apk update && apk add --no-cache jq curl
4
5 # wait for Keycloak to start
6 while ! curl -k -s https://keycloak:8443/auth/ > /dev/null ; do sleep 2 ; done
7 # wait for Apache/mod_auth_openidc to start (in Valgrind)
8 while ! curl -k -s https://apache:443/auth/ > /dev/null ; do sleep 2 ; done
9
10 # give Keycloak time to run startup scripts to create clients
11 sleep 5
12
13 # run headless JMeter for a number of threads/loops and record results in a logfile
14 /entrypoint.sh -JTHREADS=${THREADS} -JLOOP=${LOOP} -n -t /tmp/mod_auth_openidc.jmx > /tmp/mod_auth_openidc.log
15
16 # verify that there were no errors in the logfile that JMeter produced
17 cat /tmp/mod_auth_openidc.log | tail -n 10
18 grep "summary =" /tmp/mod_auth_openidc.log | grep "Err: 0 (0.00%)" || exit 1
19
20 # find out the container id of the Apache server
21 ID=$(curl -s --unix-socket /var/run/docker.sock http://localhost/containers/json | jq -r 'map(select(.Names[] | contains ("apache"))) | .[] .Id')
22 # send SIGTERM to Apache so Valgrind terminates and prints out the heap/leak summary
23 curl -s --unix-socket /var/run/docker.sock -X POST http://localhost/containers/${ID}/kill?signal=TERM
24
25 # wait until we receive a SIGTERM ourselves to ensure that the Apache
26 # exits first and terminates docker-compose --abort-on-container-exit
27 sleep infinity & PID=$!
28 trap "kill $PID" INT TERM
29
30 wait
0 #!/bin/sh
1
2 if [ -z "$1" ] ; then
3 "$0" create &
4 exit;
5 fi
6
7 PATH="${PATH}:${JBOSS_HOME}/bin"
8
9 while ! curl -k -s https://localhost:8443/auth/ > /dev/null ; do sleep 2 ; done
10
11 kcadm.sh config truststore --trustpass password /opt/jboss/keycloak/standalone/configuration/application.keystore
12 kcadm.sh config credentials --server https://localhost:8443/auth --realm master --user "${KEYCLOAK_USER}" --password "${KEYCLOAK_PASSWORD}"
13
14 # web client
15 CID=$(kcadm.sh create clients \
16 -r master \
17 -s 'redirectUris=["https://localhost/protected/", "https://apache/protected/"]' \
18 -s publicClient=false \
19 -s clientAuthenticatorType=client-secret \
20 -s clientId=web_client \
21 -s secret=mysecret \
22 -s enabled=true \
23 -i)
24 kcadm.sh get clients/$CID/installation/providers/keycloak-oidc-keycloak-json
25
26 # client credentials
27 CID=$(kcadm.sh create clients \
28 -r master \
29 -s serviceAccountsEnabled=true \
30 -s publicClient=false \
31 -s directAccessGrantsEnabled=true \
32 -s clientAuthenticatorType=client-secret \
33 -s clientId=cc_client \
34 -s secret=mysecret \
35 -s enabled=true \
36 -i)
37 kcadm.sh get clients/$CID/installation/providers/keycloak-oidc-keycloak-json
38
39 # introspection
40 CID=$(kcadm.sh create clients \
41 -r master \
42 -s serviceAccountsEnabled=true \
43 -s publicClient=false \
44 -s clientAuthenticatorType=client-secret \
45 -s clientId=introspect_client \
46 -s secret=mysecret \
47 -s enabled=true \
48 -i)
49 kcadm.sh get clients/$CID/installation/providers/keycloak-oidc-keycloak-json
00 <?xml version="1.0" encoding="UTF-8"?>
11 <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.1.1.20190725">
22 <hashTree>
3 <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="OpenID Connect Apache Module Test Plan" enabled="true">
3 <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="mod_auth_openidc test plan" enabled="true">
44 <stringProp name="TestPlan.comments"></stringProp>
55 <boolProp name="TestPlan.functional_mode">false</boolProp>
6 <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
67 <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
78 <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
89 <collectionProp name="Arguments.arguments">
9 <elementProp name="APP_SERVER" elementType="Argument">
10 <stringProp name="Argument.name">APP_SERVER</stringProp>
11 <stringProp name="Argument.value">localhost.zmartzone.eu</stringProp>
10 <elementProp name="APP_HOST" elementType="Argument">
11 <stringProp name="Argument.name">APP_HOST</stringProp>
12 <stringProp name="Argument.value">apache</stringProp>
1213 <stringProp name="Argument.metadata">=</stringProp>
1314 </elementProp>
1415 <elementProp name="APP_PORT" elementType="Argument">
1617 <stringProp name="Argument.value">443</stringProp>
1718 <stringProp name="Argument.metadata">=</stringProp>
1819 </elementProp>
19 <elementProp name="APP_PATH_USER" elementType="Argument">
20 <stringProp name="Argument.name">APP_PATH_USER</stringProp>
21 <stringProp name="Argument.value">/protected/index.php?param=sample</stringProp>
22 <stringProp name="Argument.metadata">=</stringProp>
23 </elementProp>
24 <elementProp name="AS_HOST" elementType="Argument">
25 <stringProp name="Argument.name">AS_HOST</stringProp>
26 <stringProp name="Argument.value">localhost</stringProp>
27 <stringProp name="Argument.metadata">=</stringProp>
28 </elementProp>
29 <elementProp name="AS_PORT" elementType="Argument">
30 <stringProp name="Argument.name">AS_PORT</stringProp>
31 <stringProp name="Argument.value">9031</stringProp>
32 <stringProp name="Argument.metadata">=</stringProp>
33 </elementProp>
34 <elementProp name="AS_PATH_TOKEN" elementType="Argument">
35 <stringProp name="Argument.name">AS_PATH_TOKEN</stringProp>
36 <stringProp name="Argument.value">/as/token.oauth2</stringProp>
37 <stringProp name="Argument.metadata">=</stringProp>
38 </elementProp>
39 <elementProp name="AS_CLIENT_ID" elementType="Argument">
40 <stringProp name="Argument.name">AS_CLIENT_ID</stringProp>
41 <stringProp name="Argument.value">ro_client</stringProp>
42 <stringProp name="Argument.desc">false</stringProp>
43 <stringProp name="Argument.metadata">=</stringProp>
44 </elementProp>
45 <elementProp name="AS_USERNAME" elementType="Argument">
46 <stringProp name="Argument.name">AS_USERNAME</stringProp>
47 <stringProp name="Argument.value">joe</stringProp>
48 <stringProp name="Argument.desc">false</stringProp>
49 <stringProp name="Argument.metadata">=</stringProp>
50 </elementProp>
51 <elementProp name="AS_PASSWORD" elementType="Argument">
52 <stringProp name="Argument.name">AS_PASSWORD</stringProp>
53 <stringProp name="Argument.value">2Federate</stringProp>
54 <stringProp name="Argument.desc">false</stringProp>
55 <stringProp name="Argument.metadata">=</stringProp>
56 </elementProp>
57 <elementProp name="APP_PATH_ACCESS" elementType="Argument">
58 <stringProp name="Argument.name">APP_PATH_ACCESS</stringProp>
59 <stringProp name="Argument.value">/api/index.php</stringProp>
20 <elementProp name="USERNAME" elementType="Argument">
21 <stringProp name="Argument.name">USERNAME</stringProp>
22 <stringProp name="Argument.value">admin</stringProp>
23 <stringProp name="Argument.metadata">=</stringProp>
24 </elementProp>
25 <elementProp name="PASSWORD" elementType="Argument">
26 <stringProp name="Argument.name">PASSWORD</stringProp>
27 <stringProp name="Argument.value">admin</stringProp>
28 <stringProp name="Argument.metadata">=</stringProp>
29 </elementProp>
30 <elementProp name="THREADS" elementType="Argument">
31 <stringProp name="Argument.name">THREADS</stringProp>
32 <stringProp name="Argument.value">${__P(THREADS,2)}</stringProp>
33 <stringProp name="Argument.metadata">=</stringProp>
34 </elementProp>
35 <elementProp name="LOOP" elementType="Argument">
36 <stringProp name="Argument.name">LOOP</stringProp>
37 <stringProp name="Argument.value">${__P(LOOP,2)}</stringProp>
38 <stringProp name="Argument.metadata">=</stringProp>
39 </elementProp>
40 <elementProp name="PROVIDER_HOST" elementType="Argument">
41 <stringProp name="Argument.name">PROVIDER_HOST</stringProp>
42 <stringProp name="Argument.value">keycloak</stringProp>
43 <stringProp name="Argument.metadata">=</stringProp>
44 </elementProp>
45 <elementProp name="PROVIDER_PORT" elementType="Argument">
46 <stringProp name="Argument.name">PROVIDER_PORT</stringProp>
47 <stringProp name="Argument.value">8443</stringProp>
6048 <stringProp name="Argument.metadata">=</stringProp>
6149 </elementProp>
6250 </collectionProp>
6452 <stringProp name="TestPlan.user_define_classpath"></stringProp>
6553 </TestPlan>
6654 <hashTree>
67 <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OpenID Connect User Login" enabled="true">
55 <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true">
56 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
57 <collectionProp name="Arguments.arguments"/>
58 </elementProp>
59 <stringProp name="HTTPSampler.domain"></stringProp>
60 <stringProp name="HTTPSampler.port"></stringProp>
61 <stringProp name="HTTPSampler.protocol"></stringProp>
62 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
63 <stringProp name="HTTPSampler.path"></stringProp>
64 <stringProp name="HTTPSampler.concurrentPool">6</stringProp>
65 <stringProp name="HTTPSampler.connect_timeout">10000</stringProp>
66 <stringProp name="HTTPSampler.response_timeout">20000</stringProp>
67 </ConfigTestElement>
68 <hashTree/>
69 <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OpenID Connect" enabled="true">
6870 <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp>
6971 <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
7072 <boolProp name="LoopController.continue_forever">false</boolProp>
71 <stringProp name="LoopController.loops">5</stringProp>
73 <stringProp name="LoopController.loops">${LOOP}</stringProp>
7274 </elementProp>
73 <stringProp name="ThreadGroup.num_threads">15</stringProp>
74 <stringProp name="ThreadGroup.ramp_time">0</stringProp>
75 <longProp name="ThreadGroup.start_time">1299167831000</longProp>
76 <longProp name="ThreadGroup.end_time">1299167831000</longProp>
75 <stringProp name="ThreadGroup.num_threads">${THREADS}</stringProp>
76 <stringProp name="ThreadGroup.ramp_time">1</stringProp>
7777 <boolProp name="ThreadGroup.scheduler">false</boolProp>
7878 <stringProp name="ThreadGroup.duration"></stringProp>
7979 <stringProp name="ThreadGroup.delay"></stringProp>
8080 </ThreadGroup>
8181 <hashTree>
82 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Initial Application Access" enabled="true">
82 <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
83 <collectionProp name="CookieManager.cookies"/>
84 <boolProp name="CookieManager.clearEachIteration">true</boolProp>
85 </CookieManager>
86 <hashTree/>
87 <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="Set Accept Header" enabled="true">
88 <collectionProp name="HeaderManager.headers">
89 <elementProp name="" elementType="Header">
90 <stringProp name="Header.name">Accept</stringProp>
91 <stringProp name="Header.value">text/html, */*</stringProp>
92 </elementProp>
93 </collectionProp>
94 </HeaderManager>
95 <hashTree/>
96 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Send Unauthenticated Request" enabled="true">
8397 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
84 <collectionProp name="Arguments.arguments">
85 <elementProp name="jan" elementType="HTTPArgument">
86 <boolProp name="HTTPArgument.always_encode">true</boolProp>
87 <stringProp name="Argument.value">piet</stringProp>
88 <stringProp name="Argument.metadata">=</stringProp>
89 <boolProp name="HTTPArgument.use_equals">true</boolProp>
90 <stringProp name="Argument.name">jan</stringProp>
91 </elementProp>
92 </collectionProp>
93 </elementProp>
94 <stringProp name="HTTPSampler.domain">${APP_SERVER}</stringProp>
98 <collectionProp name="Arguments.arguments"/>
99 </elementProp>
100 <stringProp name="HTTPSampler.domain">${APP_HOST}</stringProp>
95101 <stringProp name="HTTPSampler.port">${APP_PORT}</stringProp>
96102 <stringProp name="HTTPSampler.protocol">https</stringProp>
97103 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
98 <stringProp name="HTTPSampler.path">${APP_PATH_USER}</stringProp>
104 <stringProp name="HTTPSampler.path">/</stringProp>
99105 <stringProp name="HTTPSampler.method">GET</stringProp>
100 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
106 <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
101107 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
102 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
108 <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
103109 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
104110 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
105 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
106111 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
107112 <stringProp name="HTTPSampler.response_timeout"></stringProp>
108113 </HTTPSamplerProxy>
109114 <hashTree>
110 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab AuthorizationRequestPath" enabled="true">
111 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
112 <stringProp name="RegexExtractor.refname">AuthorizationRequestPath</stringProp>
113 <stringProp name="RegexExtractor.regex">Location: https://(.*?)/(.*)</stringProp>
114 <stringProp name="RegexExtractor.template">$2$</stringProp>
115 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
116 <stringProp name="RegexExtractor.match_number">1</stringProp>
117 </RegexExtractor>
115 <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="Extract Login URL" enabled="true">
116 <stringProp name="XPathExtractor.default"></stringProp>
117 <stringProp name="XPathExtractor.refname">LOGIN_URL</stringProp>
118 <stringProp name="XPathExtractor.matchNumber">-1</stringProp>
119 <stringProp name="XPathExtractor.xpathQuery">//form[@id=&quot;kc-form-login&quot;]/@action </stringProp>
120 <boolProp name="XPathExtractor.validate">false</boolProp>
121 <boolProp name="XPathExtractor.tolerant">true</boolProp>
122 <boolProp name="XPathExtractor.namespace">false</boolProp>
123 </XPathExtractor>
124 <hashTree/>
125 <BeanShellPostProcessor guiclass="TestBeanGUI" testclass="BeanShellPostProcessor" testname="Extract Login Components" enabled="true">
126 <stringProp name="filename"></stringProp>
127 <stringProp name="parameters"></stringProp>
128 <boolProp name="resetInterpreter">false</boolProp>
129 <stringProp name="script">URL url = new URL(vars.get(&quot;LOGIN_URL&quot;));
130 vars.put(&quot;LOGIN_PROTO&quot;, url.getProtocol());
131 vars.put(&quot;LOGIN_HOST&quot;, url.getHost());
132 vars.put(&quot;LOGIN_PORT&quot;, Integer.toString(url.getPort()));
133 vars.put(&quot;LOGIN_PATH&quot;, url.getPath() + &quot;?&quot; + url.getQuery());</stringProp>
134 </BeanShellPostProcessor>
118135 <hashTree/>
119136 </hashTree>
120 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Authorization Request" enabled="true">
121 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
122 <collectionProp name="Arguments.arguments"/>
123 </elementProp>
124 <stringProp name="HTTPSampler.domain">${AS_HOST}</stringProp>
125 <stringProp name="HTTPSampler.port">${AS_PORT}</stringProp>
126 <stringProp name="HTTPSampler.protocol">https</stringProp>
127 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
128 <stringProp name="HTTPSampler.path">/${AuthorizationRequestPath}</stringProp>
129 <stringProp name="HTTPSampler.method">GET</stringProp>
130 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
131 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
132 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
133 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
134 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
135 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
136 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
137 <stringProp name="HTTPSampler.response_timeout"></stringProp>
138 </HTTPSamplerProxy>
139 <hashTree>
140 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab AuthzResumePath" enabled="true">
141 <stringProp name="RegexExtractor.useHeaders">false</stringProp>
142 <stringProp name="RegexExtractor.refname">AuthzResumePath</stringProp>
143 <stringProp name="RegexExtractor.regex">&lt;form method=\&quot;POST&quot;\ action=\&quot;(.+)&quot; autocomplete=&quot;off&quot;&gt;</stringProp>
144 <stringProp name="RegexExtractor.template">$1$</stringProp>
145 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
146 <stringProp name="RegexExtractor.match_number">1</stringProp>
147 </RegexExtractor>
148 <hashTree/>
149 </hashTree>
150 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="OP Adapter Selection" enabled="false">
137 <DebugSampler guiclass="TestBeanGUI" testclass="DebugSampler" testname="Debug Sampler" enabled="false">
138 <boolProp name="displayJMeterProperties">false</boolProp>
139 <boolProp name="displayJMeterVariables">true</boolProp>
140 <boolProp name="displaySystemProperties">false</boolProp>
141 </DebugSampler>
142 <hashTree/>
143 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Provider Login" enabled="true">
151144 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
152145 <collectionProp name="Arguments.arguments">
153 <elementProp name="pfidpadapterid" elementType="HTTPArgument">
154 <boolProp name="HTTPArgument.always_encode">true</boolProp>
155 <stringProp name="Argument.value">OTIdPJava</stringProp>
156 <stringProp name="Argument.metadata">=</stringProp>
157 <boolProp name="HTTPArgument.use_equals">true</boolProp>
158 <stringProp name="Argument.name">pfidpadapterid</stringProp>
159 </elementProp>
160 </collectionProp>
161 </elementProp>
162 <stringProp name="HTTPSampler.domain">${AS_HOST}</stringProp>
163 <stringProp name="HTTPSampler.port">${AS_PORT}</stringProp>
164 <stringProp name="HTTPSampler.protocol">https</stringProp>
165 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
166 <stringProp name="HTTPSampler.path">${AuthzResumePath}</stringProp>
167 <stringProp name="HTTPSampler.method">GET</stringProp>
168 <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
169 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
170 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
171 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
172 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
173 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
174 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
175 <stringProp name="HTTPSampler.response_timeout"></stringProp>
176 </HTTPSamplerProxy>
177 <hashTree>
178 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab ResumeParam" enabled="true">
179 <stringProp name="RegexExtractor.useHeaders">false</stringProp>
180 <stringProp name="RegexExtractor.refname">ResumeParam</stringProp>
181 <stringProp name="RegexExtractor.regex">&lt;input type=\&quot;hidden\&quot; name=\&quot;resume\&quot; value=\&quot;(.+)\&quot;&gt;</stringProp>
182 <stringProp name="RegexExtractor.template">$1$</stringProp>
183 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
184 <stringProp name="RegexExtractor.match_number">1</stringProp>
185 </RegexExtractor>
186 <hashTree/>
187 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab LoginPath" enabled="true">
188 <stringProp name="RegexExtractor.useHeaders">false</stringProp>
189 <stringProp name="RegexExtractor.refname">LoginPath</stringProp>
190 <stringProp name="RegexExtractor.regex">form method=\&quot;post\&quot; action=\&quot;(.+)\&quot;&gt;</stringProp>
191 <stringProp name="RegexExtractor.template">$1$</stringProp>
192 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
193 <stringProp name="RegexExtractor.match_number">1</stringProp>
194 </RegexExtractor>
195 <hashTree/>
196 </hashTree>
197 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Implict: OP User Login" enabled="false">
198 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
199 <collectionProp name="Arguments.arguments">
200 <elementProp name="resume" elementType="HTTPArgument">
201 <boolProp name="HTTPArgument.always_encode">true</boolProp>
202 <stringProp name="Argument.value">${ResumeParam}</stringProp>
203 <stringProp name="Argument.metadata">=</stringProp>
204 <boolProp name="HTTPArgument.use_equals">true</boolProp>
205 <stringProp name="Argument.name">resume</stringProp>
206 </elementProp>
207 <elementProp name="userName" elementType="HTTPArgument">
146 <elementProp name="username" elementType="HTTPArgument">
208147 <boolProp name="HTTPArgument.always_encode">true</boolProp>
209148 <stringProp name="Argument.value">${USERNAME}</stringProp>
210149 <stringProp name="Argument.metadata">=</stringProp>
211150 <boolProp name="HTTPArgument.use_equals">true</boolProp>
212 <stringProp name="Argument.name">userName</stringProp>
151 <stringProp name="Argument.name">username</stringProp>
213152 </elementProp>
214153 <elementProp name="password" elementType="HTTPArgument">
215154 <boolProp name="HTTPArgument.always_encode">true</boolProp>
220159 </elementProp>
221160 </collectionProp>
222161 </elementProp>
223 <stringProp name="HTTPSampler.domain">${AS_HOST}</stringProp>
224 <stringProp name="HTTPSampler.port">${AS_PORT}</stringProp>
225 <stringProp name="HTTPSampler.protocol">https</stringProp>
162 <stringProp name="HTTPSampler.domain">${LOGIN_HOST}</stringProp>
163 <stringProp name="HTTPSampler.port">${LOGIN_PORT}</stringProp>
164 <stringProp name="HTTPSampler.protocol">${LOGIN_PROTO}</stringProp>
226165 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
227 <stringProp name="HTTPSampler.path">/IdpSample/MainPage?cmd=login</stringProp>
228 <stringProp name="HTTPSampler.method">POST</stringProp>
229 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
230 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
231 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
232 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
233 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
234 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
235 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
236 <stringProp name="HTTPSampler.response_timeout"></stringProp>
237 </HTTPSamplerProxy>
238 <hashTree>
239 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab ResumePath" enabled="true">
240 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
241 <stringProp name="RegexExtractor.refname">ResumePath</stringProp>
242 <stringProp name="RegexExtractor.regex">Location: https://(.*?)/(.*)</stringProp>
243 <stringProp name="RegexExtractor.template">$2$</stringProp>
244 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
245 <stringProp name="RegexExtractor.match_number">1</stringProp>
246 </RegexExtractor>
247 <hashTree/>
248 </hashTree>
249 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Implict: Resume Authorization" enabled="false">
250 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
251 <collectionProp name="Arguments.arguments"/>
252 </elementProp>
253 <stringProp name="HTTPSampler.domain">${AS_HOST}</stringProp>
254 <stringProp name="HTTPSampler.port">${AS_PORT}</stringProp>
255 <stringProp name="HTTPSampler.protocol">https</stringProp>
256 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
257 <stringProp name="HTTPSampler.path">${ResumePath}</stringProp>
258 <stringProp name="HTTPSampler.method">POST</stringProp>
259 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
260 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
261 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
262 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
263 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
264 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
265 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
266 <stringProp name="HTTPSampler.response_timeout"></stringProp>
267 </HTTPSamplerProxy>
268 <hashTree>
269 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab RedirectURIPath" enabled="true">
270 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
271 <stringProp name="RegexExtractor.refname">RedirectURIPath</stringProp>
272 <stringProp name="RegexExtractor.regex">Location: https://(.*?)/(.*)#</stringProp>
273 <stringProp name="RegexExtractor.template">$2$</stringProp>
274 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
275 <stringProp name="RegexExtractor.match_number">1</stringProp>
276 </RegexExtractor>
277 <hashTree/>
278 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab StateFragment" enabled="true">
279 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
280 <stringProp name="RegexExtractor.refname">StateFragment</stringProp>
281 <stringProp name="RegexExtractor.regex">Location: https://(.*?)#(.*?)state=(.*?)&amp;</stringProp>
282 <stringProp name="RegexExtractor.template">$3$</stringProp>
283 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
284 <stringProp name="RegexExtractor.match_number">1</stringProp>
285 </RegexExtractor>
286 <hashTree/>
287 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab IDTokenFragment" enabled="true">
288 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
289 <stringProp name="RegexExtractor.refname">IDTokenFragment</stringProp>
290 <stringProp name="RegexExtractor.regex">Location: https://(.*?)#(.*?)id_token=(.*)</stringProp>
291 <stringProp name="RegexExtractor.template">$3$</stringProp>
292 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
293 <stringProp name="RegexExtractor.match_number">1</stringProp>
294 </RegexExtractor>
295 <hashTree/>
296 </hashTree>
297 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Implicit: Authorization Response" enabled="false">
298 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
299 <collectionProp name="Arguments.arguments">
300 <elementProp name="state" elementType="HTTPArgument">
301 <boolProp name="HTTPArgument.always_encode">false</boolProp>
302 <stringProp name="Argument.value">${StateFragment}</stringProp>
303 <stringProp name="Argument.metadata">=</stringProp>
304 <boolProp name="HTTPArgument.use_equals">true</boolProp>
305 <stringProp name="Argument.name">state</stringProp>
306 </elementProp>
307 <elementProp name="id_token" elementType="HTTPArgument">
308 <boolProp name="HTTPArgument.always_encode">false</boolProp>
309 <stringProp name="Argument.value">${IDTokenFragment}</stringProp>
310 <stringProp name="Argument.metadata">=</stringProp>
311 <boolProp name="HTTPArgument.use_equals">true</boolProp>
312 <stringProp name="Argument.name">id_token</stringProp>
313 </elementProp>
314 </collectionProp>
315 </elementProp>
316 <stringProp name="HTTPSampler.domain">${APP_SERVER}</stringProp>
317 <stringProp name="HTTPSampler.port">${APP_PORT}</stringProp>
318 <stringProp name="HTTPSampler.protocol">https</stringProp>
319 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
320 <stringProp name="HTTPSampler.path">/${RedirectURIPath}</stringProp>
321 <stringProp name="HTTPSampler.method">POST</stringProp>
322 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
323 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
324 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
325 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
326 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
327 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
328 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
329 <stringProp name="HTTPSampler.response_timeout"></stringProp>
330 </HTTPSamplerProxy>
331 <hashTree>
332 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab ApplicationPath" enabled="true">
333 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
334 <stringProp name="RegexExtractor.refname">ApplicationPath</stringProp>
335 <stringProp name="RegexExtractor.regex">Location: https://(.*?)/(.*)</stringProp>
336 <stringProp name="RegexExtractor.template">$2$</stringProp>
337 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
338 <stringProp name="RegexExtractor.match_number">1</stringProp>
339 </RegexExtractor>
340 <hashTree/>
341 </hashTree>
342 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Basic: OP User Login Consent" enabled="true">
343 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
344 <collectionProp name="Arguments.arguments">
345 <elementProp name="pf.username" elementType="HTTPArgument">
346 <boolProp name="HTTPArgument.always_encode">true</boolProp>
347 <stringProp name="Argument.value">${USERNAME}</stringProp>
348 <stringProp name="Argument.metadata">=</stringProp>
349 <boolProp name="HTTPArgument.use_equals">true</boolProp>
350 <stringProp name="Argument.name">pf.username</stringProp>
351 </elementProp>
352 <elementProp name="pf.pass" elementType="HTTPArgument">
353 <boolProp name="HTTPArgument.always_encode">true</boolProp>
354 <stringProp name="Argument.value">${PASSWORD}</stringProp>
355 <stringProp name="Argument.metadata">=</stringProp>
356 <boolProp name="HTTPArgument.use_equals">true</boolProp>
357 <stringProp name="Argument.name">pf.pass</stringProp>
358 </elementProp>
359 </collectionProp>
360 </elementProp>
361 <stringProp name="HTTPSampler.domain">${AS_HOST}</stringProp>
362 <stringProp name="HTTPSampler.port">${AS_PORT}</stringProp>
363 <stringProp name="HTTPSampler.protocol">https</stringProp>
364 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
365 <stringProp name="HTTPSampler.path">${AuthzResumePath}</stringProp>
166 <stringProp name="HTTPSampler.path">${LOGIN_PATH}</stringProp>
366167 <stringProp name="HTTPSampler.method">POST</stringProp>
367168 <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
368169 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
369 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
370 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
371 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
372 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
373 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
374 <stringProp name="HTTPSampler.response_timeout"></stringProp>
375 </HTTPSamplerProxy>
376 <hashTree>
377 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab cSRFToken Parameter" enabled="true">
378 <stringProp name="RegexExtractor.useHeaders">false</stringProp>
379 <stringProp name="RegexExtractor.refname">cSRFTokenParam</stringProp>
380 <stringProp name="RegexExtractor.regex">&lt;input type=\&quot;hidden\&quot; name=\&quot;cSRFToken\&quot; value=\&quot;(.+)\&quot;/&gt;</stringProp>
381 <stringProp name="RegexExtractor.template">$1$</stringProp>
382 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
383 <stringProp name="RegexExtractor.match_number">1</stringProp>
384 </RegexExtractor>
385 <hashTree/>
386 </hashTree>
387 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Basic: OP User Consent" enabled="true">
388 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
389 <collectionProp name="Arguments.arguments">
390 <elementProp name="check-user-approved-scope" elementType="HTTPArgument">
391 <boolProp name="HTTPArgument.always_encode">true</boolProp>
392 <stringProp name="Argument.value">true</stringProp>
393 <stringProp name="Argument.metadata">=</stringProp>
394 <boolProp name="HTTPArgument.use_equals">true</boolProp>
395 <stringProp name="Argument.name">check-user-approved-scope</stringProp>
396 </elementProp>
397 <elementProp name="scope" elementType="HTTPArgument">
398 <boolProp name="HTTPArgument.always_encode">true</boolProp>
399 <stringProp name="Argument.value">openid</stringProp>
400 <stringProp name="Argument.metadata">=</stringProp>
401 <boolProp name="HTTPArgument.use_equals">true</boolProp>
402 <stringProp name="Argument.name">scope</stringProp>
403 </elementProp>
404 <elementProp name="scope" elementType="HTTPArgument">
405 <boolProp name="HTTPArgument.always_encode">true</boolProp>
406 <stringProp name="Argument.value">email</stringProp>
407 <stringProp name="Argument.metadata">=</stringProp>
408 <boolProp name="HTTPArgument.use_equals">true</boolProp>
409 <stringProp name="Argument.name">scope</stringProp>
410 </elementProp>
411 <elementProp name="scope" elementType="HTTPArgument">
412 <boolProp name="HTTPArgument.always_encode">true</boolProp>
413 <stringProp name="Argument.value">profile</stringProp>
414 <stringProp name="Argument.metadata">=</stringProp>
415 <boolProp name="HTTPArgument.use_equals">true</boolProp>
416 <stringProp name="Argument.name">scope</stringProp>
417 </elementProp>
418 <elementProp name="cSRFToken" elementType="HTTPArgument">
419 <boolProp name="HTTPArgument.always_encode">true</boolProp>
420 <stringProp name="Argument.value">${cSRFTokenParam}</stringProp>
421 <stringProp name="Argument.metadata">=</stringProp>
422 <boolProp name="HTTPArgument.use_equals">true</boolProp>
423 <stringProp name="Argument.name">cSRFToken</stringProp>
424 </elementProp>
425 <elementProp name="pf.oauth.authz.consent" elementType="HTTPArgument">
426 <boolProp name="HTTPArgument.always_encode">true</boolProp>
427 <stringProp name="Argument.value">allow</stringProp>
428 <stringProp name="Argument.metadata">=</stringProp>
429 <boolProp name="HTTPArgument.use_equals">true</boolProp>
430 <stringProp name="Argument.name">pf.oauth.authz.consent</stringProp>
431 </elementProp>
432 </collectionProp>
433 </elementProp>
434 <stringProp name="HTTPSampler.domain">${AS_HOST}</stringProp>
435 <stringProp name="HTTPSampler.port">${AS_PORT}</stringProp>
436 <stringProp name="HTTPSampler.protocol">https</stringProp>
437 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
438 <stringProp name="HTTPSampler.path">${AuthzResumePath}</stringProp>
439 <stringProp name="HTTPSampler.method">POST</stringProp>
440 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
441 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
442 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
443 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
444 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
445 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
446 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
447 <stringProp name="HTTPSampler.response_timeout"></stringProp>
448 </HTTPSamplerProxy>
449 <hashTree>
450 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab LocationPath" enabled="true">
451 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
452 <stringProp name="RegexExtractor.refname">LocationPath</stringProp>
453 <stringProp name="RegexExtractor.regex">Location: https://(.*?)/(.*)</stringProp>
454 <stringProp name="RegexExtractor.template">$2$</stringProp>
455 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
456 <stringProp name="RegexExtractor.match_number">1</stringProp>
457 </RegexExtractor>
458 <hashTree/>
459 </hashTree>
460 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Basic: Authorization Response" enabled="true">
461 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
462 <collectionProp name="Arguments.arguments"/>
463 </elementProp>
464 <stringProp name="HTTPSampler.domain">${APP_SERVER}</stringProp>
465 <stringProp name="HTTPSampler.port">${APP_PORT}</stringProp>
466 <stringProp name="HTTPSampler.protocol">https</stringProp>
467 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
468 <stringProp name="HTTPSampler.path">/${LocationPath}</stringProp>
469 <stringProp name="HTTPSampler.method">GET</stringProp>
470 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
471 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
472 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
473 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
474 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
475 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
476 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
477 <stringProp name="HTTPSampler.response_timeout"></stringProp>
478 </HTTPSamplerProxy>
479 <hashTree>
480 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab ApplicationPath" enabled="true">
481 <stringProp name="RegexExtractor.useHeaders">true</stringProp>
482 <stringProp name="RegexExtractor.refname">ApplicationPath</stringProp>
483 <stringProp name="RegexExtractor.regex">Location: https://(.*?)/(.*)</stringProp>
484 <stringProp name="RegexExtractor.template">$2$</stringProp>
485 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
486 <stringProp name="RegexExtractor.match_number">1</stringProp>
487 </RegexExtractor>
488 <hashTree/>
489 </hashTree>
490 <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="Set Malicious Header" enabled="false">
491 <collectionProp name="HeaderManager.headers">
492 <elementProp name="" elementType="Header">
493 <stringProp name="Header.name">OIDC_CLAIM_BOGUS</stringProp>
494 <stringProp name="Header.value">bogus</stringProp>
495 </elementProp>
496 </collectionProp>
497 </HeaderManager>
498 <hashTree/>
499 <LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Authenticated Application Access" enabled="true">
500 <boolProp name="LoopController.continue_forever">true</boolProp>
501 <stringProp name="LoopController.loops">5</stringProp>
502 </LoopController>
503 <hashTree>
504 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Authenticated Application Access" enabled="true">
505 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
506 <collectionProp name="Arguments.arguments"/>
507 </elementProp>
508 <stringProp name="HTTPSampler.domain">${APP_SERVER}</stringProp>
509 <stringProp name="HTTPSampler.port">${APP_PORT}</stringProp>
510 <stringProp name="HTTPSampler.protocol">https</stringProp>
511 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
512 <stringProp name="HTTPSampler.path">/${ApplicationPath}</stringProp>
513 <stringProp name="HTTPSampler.method">GET</stringProp>
514 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
515 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
516 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
517 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
518 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
519 <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
520 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
521 <stringProp name="HTTPSampler.response_timeout"></stringProp>
522 </HTTPSamplerProxy>
523 <hashTree>
524 <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert User Logged In" enabled="true">
525 <collectionProp name="Asserion.test_strings">
526 <stringProp name="-1682027846">\[OIDC_CLAIM_sub\] =&gt; ${USERNAME}</stringProp>
527 </collectionProp>
528 <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
529 <boolProp name="Assertion.assume_success">false</boolProp>
530 <intProp name="Assertion.test_type">2</intProp>
531 <stringProp name="Assertion.custom_message"></stringProp>
532 </ResponseAssertion>
533 <hashTree/>
534 <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Fake Header Removal" enabled="true">
535 <collectionProp name="Asserion.test_strings">
536 <stringProp name="-2019701846">\[OIDC_CLAIM_BOGUS\] =&gt; bogus</stringProp>
537 </collectionProp>
538 <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
539 <boolProp name="Assertion.assume_success">false</boolProp>
540 <intProp name="Assertion.test_type">6</intProp>
541 <stringProp name="Assertion.custom_message"></stringProp>
542 </ResponseAssertion>
543 <hashTree/>
544 </hashTree>
545 </hashTree>
546 <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
547 <collectionProp name="CookieManager.cookies"/>
548 <boolProp name="CookieManager.clearEachIteration">true</boolProp>
549 <stringProp name="CookieManager.policy">rfc2109</stringProp>
550 </CookieManager>
551 <hashTree/>
552 <CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="Username/Password Data Set" enabled="true">
553 <stringProp name="delimiter">,</stringProp>
554 <stringProp name="fileEncoding"></stringProp>
555 <stringProp name="filename">users.txt</stringProp>
556 <boolProp name="quotedData">false</boolProp>
557 <boolProp name="recycle">true</boolProp>
558 <stringProp name="shareMode">shareMode.all</stringProp>
559 <boolProp name="stopThread">false</boolProp>
560 <stringProp name="variableNames">USERNAME,PASSWORD</stringProp>
561 <boolProp name="ignoreFirstLine">false</boolProp>
562 </CSVDataSet>
563 <hashTree/>
564 <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
565 <collectionProp name="HeaderManager.headers">
566 <elementProp name="" elementType="Header">
567 <stringProp name="Header.name">Accept</stringProp>
568 <stringProp name="Header.value">*/*</stringProp>
569 </elementProp>
570 </collectionProp>
571 </HeaderManager>
572 <hashTree/>
573 </hashTree>
574 <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OAuth Resource Access" enabled="true">
575 <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp>
576 <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
577 <boolProp name="LoopController.continue_forever">false</boolProp>
578 <stringProp name="LoopController.loops">5</stringProp>
579 </elementProp>
580 <stringProp name="ThreadGroup.num_threads">15</stringProp>
581 <stringProp name="ThreadGroup.ramp_time">0</stringProp>
582 <longProp name="ThreadGroup.start_time">1388176686000</longProp>
583 <longProp name="ThreadGroup.end_time">1388176686000</longProp>
584 <boolProp name="ThreadGroup.scheduler">false</boolProp>
585 <stringProp name="ThreadGroup.duration"></stringProp>
586 <stringProp name="ThreadGroup.delay"></stringProp>
587 </ThreadGroup>
588 <hashTree>
589 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Token Request" enabled="true">
590 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
591 <collectionProp name="Arguments.arguments">
592 <elementProp name="client_id" elementType="HTTPArgument">
593 <boolProp name="HTTPArgument.always_encode">false</boolProp>
594 <stringProp name="Argument.value">${AS_CLIENT_ID}</stringProp>
595 <stringProp name="Argument.metadata">=</stringProp>
596 <boolProp name="HTTPArgument.use_equals">true</boolProp>
597 <stringProp name="Argument.name">client_id</stringProp>
598 </elementProp>
599 <elementProp name="grant_type" elementType="HTTPArgument">
600 <boolProp name="HTTPArgument.always_encode">false</boolProp>
601 <stringProp name="Argument.value">password</stringProp>
602 <stringProp name="Argument.metadata">=</stringProp>
603 <boolProp name="HTTPArgument.use_equals">true</boolProp>
604 <stringProp name="Argument.name">grant_type</stringProp>
605 </elementProp>
606 <elementProp name="username" elementType="HTTPArgument">
607 <boolProp name="HTTPArgument.always_encode">false</boolProp>
608 <stringProp name="Argument.value">${AS_USERNAME}</stringProp>
609 <stringProp name="Argument.metadata">=</stringProp>
610 <boolProp name="HTTPArgument.use_equals">true</boolProp>
611 <stringProp name="Argument.name">username</stringProp>
612 </elementProp>
613 <elementProp name="password" elementType="HTTPArgument">
614 <boolProp name="HTTPArgument.always_encode">false</boolProp>
615 <stringProp name="Argument.value">${AS_PASSWORD}</stringProp>
616 <stringProp name="Argument.metadata">=</stringProp>
617 <boolProp name="HTTPArgument.use_equals">true</boolProp>
618 <stringProp name="Argument.name">password</stringProp>
619 </elementProp>
620 </collectionProp>
621 </elementProp>
622 <stringProp name="HTTPSampler.domain">${AS_HOST}</stringProp>
623 <stringProp name="HTTPSampler.port">${AS_PORT}</stringProp>
624 <stringProp name="HTTPSampler.protocol">https</stringProp>
625 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
626 <stringProp name="HTTPSampler.path">${AS_PATH_TOKEN}</stringProp>
627 <stringProp name="HTTPSampler.method">POST</stringProp>
628 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
629 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
630 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
170 <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
631171 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
632172 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
633173 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
634174 <stringProp name="HTTPSampler.response_timeout"></stringProp>
635175 </HTTPSamplerProxy>
636176 <hashTree>
637 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Grab AccessToken" enabled="true">
638 <stringProp name="RegexExtractor.useHeaders">false</stringProp>
639 <stringProp name="RegexExtractor.refname">AccessToken</stringProp>
640 <stringProp name="RegexExtractor.regex">\&quot;access_token\&quot;:\&quot;(.+)\&quot;,\&quot;token_type\&quot;</stringProp>
641 <stringProp name="RegexExtractor.template">$1$</stringProp>
642 <stringProp name="RegexExtractor.default">REGEX_FAILED</stringProp>
643 <stringProp name="RegexExtractor.match_number">1</stringProp>
644 </RegexExtractor>
177 <JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="Assert Preferred Username Header" enabled="true">
178 <stringProp name="JSON_PATH">$.headers.oidc_claim_preferred_username</stringProp>
179 <stringProp name="EXPECTED_VALUE">admin</stringProp>
180 <boolProp name="JSONVALIDATION">true</boolProp>
181 <boolProp name="EXPECT_NULL">false</boolProp>
182 <boolProp name="INVERT">false</boolProp>
183 <boolProp name="ISREGEX">false</boolProp>
184 </JSONPathAssertion>
645185 <hashTree/>
646186 </hashTree>
647 <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="Set Authorization Bearer Token" enabled="true">
648 <collectionProp name="HeaderManager.headers">
649 <elementProp name="" elementType="Header">
650 <stringProp name="Header.name">Authorization</stringProp>
651 <stringProp name="Header.value">bearer ${AccessToken}</stringProp>
652 </elementProp>
653 <elementProp name="" elementType="Header">
654 <stringProp name="Header.name">Accept</stringProp>
655 <stringProp name="Header.value">application/json</stringProp>
656 </elementProp>
657 </collectionProp>
658 </HeaderManager>
659 <hashTree/>
660 <LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Resource Access Requests" enabled="true">
187 <LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Authenticated Requests" enabled="true">
661188 <boolProp name="LoopController.continue_forever">true</boolProp>
662 <stringProp name="LoopController.loops">5</stringProp>
189 <stringProp name="LoopController.loops">${LOOP}</stringProp>
663190 </LoopController>
664191 <hashTree>
665 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Resource Access" enabled="true">
192 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Send Authenticated Request" enabled="true">
666193 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
667194 <collectionProp name="Arguments.arguments"/>
668195 </elementProp>
669 <stringProp name="HTTPSampler.domain">${APP_SERVER}</stringProp>
196 <stringProp name="HTTPSampler.domain">${APP_HOST}</stringProp>
670197 <stringProp name="HTTPSampler.port">${APP_PORT}</stringProp>
671198 <stringProp name="HTTPSampler.protocol">https</stringProp>
672199 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
673 <stringProp name="HTTPSampler.path">${APP_PATH_ACCESS}</stringProp>
200 <stringProp name="HTTPSampler.path">/</stringProp>
674201 <stringProp name="HTTPSampler.method">GET</stringProp>
675 <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
202 <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
676203 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
677 <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
204 <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
678205 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
679206 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
680207 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
681208 <stringProp name="HTTPSampler.response_timeout"></stringProp>
682209 </HTTPSamplerProxy>
683210 <hashTree>
684 <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert AS_USERNAME" enabled="true">
685 <collectionProp name="Asserion.test_strings">
686 <stringProp name="240033137">\[OIDC_CLAIM_Username\] =&gt; ${AS_USERNAME}</stringProp>
687 </collectionProp>
688 <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
689 <boolProp name="Assertion.assume_success">false</boolProp>
690 <intProp name="Assertion.test_type">2</intProp>
691 <stringProp name="Assertion.custom_message"></stringProp>
692 </ResponseAssertion>
211 <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="Extract Login URL" enabled="true">
212 <stringProp name="XPathExtractor.default"></stringProp>
213 <stringProp name="XPathExtractor.refname">LOGIN_URL</stringProp>
214 <stringProp name="XPathExtractor.matchNumber">-1</stringProp>
215 <stringProp name="XPathExtractor.xpathQuery">//form[@id=&quot;kc-form-login&quot;]/@action </stringProp>
216 <boolProp name="XPathExtractor.validate">false</boolProp>
217 <boolProp name="XPathExtractor.tolerant">true</boolProp>
218 <boolProp name="XPathExtractor.namespace">false</boolProp>
219 </XPathExtractor>
220 <hashTree/>
221 <BeanShellPostProcessor guiclass="TestBeanGUI" testclass="BeanShellPostProcessor" testname="Extract Login Components" enabled="true">
222 <stringProp name="filename"></stringProp>
223 <stringProp name="parameters"></stringProp>
224 <boolProp name="resetInterpreter">false</boolProp>
225 <stringProp name="script">URL url = new URL(vars.get(&quot;LOGIN_URL&quot;));
226 vars.put(&quot;LOGIN_PROTO&quot;, url.getProtocol());
227 vars.put(&quot;LOGIN_HOST&quot;, url.getHost());
228 vars.put(&quot;LOGIN_PORT&quot;, Integer.toString(url.getPort()));
229 vars.put(&quot;LOGIN_PATH&quot;, url.getPath() + &quot;?&quot; + url.getQuery());</stringProp>
230 </BeanShellPostProcessor>
231 <hashTree/>
232 </hashTree>
233 </hashTree>
234 </hashTree>
235 <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OAuth 2.0" enabled="true">
236 <stringProp name="ThreadGroup.on_sample_error">stopthread</stringProp>
237 <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
238 <boolProp name="LoopController.continue_forever">false</boolProp>
239 <stringProp name="LoopController.loops">${LOOP}</stringProp>
240 </elementProp>
241 <stringProp name="ThreadGroup.num_threads">${THREADS}</stringProp>
242 <stringProp name="ThreadGroup.ramp_time">1</stringProp>
243 <boolProp name="ThreadGroup.scheduler">false</boolProp>
244 <stringProp name="ThreadGroup.duration"></stringProp>
245 <stringProp name="ThreadGroup.delay"></stringProp>
246 </ThreadGroup>
247 <hashTree>
248 <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="Set Accept Header" enabled="true">
249 <collectionProp name="HeaderManager.headers">
250 <elementProp name="" elementType="Header">
251 <stringProp name="Header.name">Accept</stringProp>
252 <stringProp name="Header.value">application/json</stringProp>
253 </elementProp>
254 </collectionProp>
255 </HeaderManager>
256 <hashTree/>
257 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Execute Client Credentials" enabled="true">
258 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
259 <collectionProp name="Arguments.arguments">
260 <elementProp name="grant_type" elementType="HTTPArgument">
261 <boolProp name="HTTPArgument.always_encode">false</boolProp>
262 <stringProp name="Argument.value">client_credentials</stringProp>
263 <stringProp name="Argument.metadata">=</stringProp>
264 <boolProp name="HTTPArgument.use_equals">true</boolProp>
265 <stringProp name="Argument.name">grant_type</stringProp>
266 </elementProp>
267 <elementProp name="client_id" elementType="HTTPArgument">
268 <boolProp name="HTTPArgument.always_encode">false</boolProp>
269 <stringProp name="Argument.value">cc_client</stringProp>
270 <stringProp name="Argument.metadata">=</stringProp>
271 <boolProp name="HTTPArgument.use_equals">true</boolProp>
272 <stringProp name="Argument.name">client_id</stringProp>
273 </elementProp>
274 <elementProp name="client_secret" elementType="HTTPArgument">
275 <boolProp name="HTTPArgument.always_encode">false</boolProp>
276 <stringProp name="Argument.value">mysecret</stringProp>
277 <stringProp name="Argument.metadata">=</stringProp>
278 <boolProp name="HTTPArgument.use_equals">true</boolProp>
279 <stringProp name="Argument.name">client_secret</stringProp>
280 </elementProp>
281 </collectionProp>
282 </elementProp>
283 <stringProp name="HTTPSampler.domain">${PROVIDER_HOST}</stringProp>
284 <stringProp name="HTTPSampler.port">${PROVIDER_PORT}</stringProp>
285 <stringProp name="HTTPSampler.protocol">https</stringProp>
286 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
287 <stringProp name="HTTPSampler.path">/auth/realms/master/protocol/openid-connect/token</stringProp>
288 <stringProp name="HTTPSampler.method">POST</stringProp>
289 <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
290 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
291 <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
292 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
293 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
294 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
295 <stringProp name="HTTPSampler.response_timeout"></stringProp>
296 </HTTPSamplerProxy>
297 <hashTree>
298 <JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Extract Access Token" enabled="true">
299 <stringProp name="JSONPostProcessor.referenceNames">ACCESS_TOKEN</stringProp>
300 <stringProp name="JSONPostProcessor.jsonPathExprs">$.access_token</stringProp>
301 <stringProp name="JSONPostProcessor.match_numbers"></stringProp>
302 </JSONPostProcessor>
303 <hashTree/>
304 </hashTree>
305 <DebugSampler guiclass="TestBeanGUI" testclass="DebugSampler" testname="Debug Sampler" enabled="false">
306 <boolProp name="displayJMeterProperties">false</boolProp>
307 <boolProp name="displayJMeterVariables">true</boolProp>
308 <boolProp name="displaySystemProperties">false</boolProp>
309 </DebugSampler>
310 <hashTree/>
311 <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="Set Authorization Header" enabled="true">
312 <collectionProp name="HeaderManager.headers">
313 <elementProp name="" elementType="Header">
314 <stringProp name="Header.name">Accept</stringProp>
315 <stringProp name="Header.value">application/json</stringProp>
316 </elementProp>
317 <elementProp name="" elementType="Header">
318 <stringProp name="Header.name">Authorization</stringProp>
319 <stringProp name="Header.value">bearer ${ACCESS_TOKEN}</stringProp>
320 </elementProp>
321 </collectionProp>
322 </HeaderManager>
323 <hashTree/>
324 <LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Authenticated Requests" enabled="true">
325 <boolProp name="LoopController.continue_forever">true</boolProp>
326 <stringProp name="LoopController.loops">${LOOP}</stringProp>
327 </LoopController>
328 <hashTree>
329 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Send Authenticated Request" enabled="true">
330 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
331 <collectionProp name="Arguments.arguments"/>
332 </elementProp>
333 <stringProp name="HTTPSampler.domain">${APP_HOST}</stringProp>
334 <stringProp name="HTTPSampler.port">${APP_PORT}</stringProp>
335 <stringProp name="HTTPSampler.protocol">https</stringProp>
336 <stringProp name="HTTPSampler.contentEncoding"></stringProp>
337 <stringProp name="HTTPSampler.path">/api</stringProp>
338 <stringProp name="HTTPSampler.method">GET</stringProp>
339 <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
340 <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
341 <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
342 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
343 <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
344 <stringProp name="HTTPSampler.connect_timeout"></stringProp>
345 <stringProp name="HTTPSampler.response_timeout"></stringProp>
346 </HTTPSamplerProxy>
347 <hashTree>
348 <JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="Assert Client ID Header" enabled="true">
349 <stringProp name="JSON_PATH">$.headers.oidc_claim_clientid</stringProp>
350 <stringProp name="EXPECTED_VALUE">cc_client</stringProp>
351 <boolProp name="JSONVALIDATION">true</boolProp>
352 <boolProp name="EXPECT_NULL">false</boolProp>
353 <boolProp name="INVERT">false</boolProp>
354 <boolProp name="ISREGEX">false</boolProp>
355 </JSONPathAssertion>
693356 <hashTree/>
694357 </hashTree>
695358 </hashTree>
722385 <assertionsResultsToSave>0</assertionsResultsToSave>
723386 <bytes>true</bytes>
724387 <sentBytes>true</sentBytes>
388 <url>true</url>
725389 <threadCounts>true</threadCounts>
726390 <idleTime>true</idleTime>
727391 <connectTime>true</connectTime>
728 </value>
729 </objProp>
730 <objProp>
731 <name></name>
732 <value class="SampleSaveConfiguration">
733 <time>true</time>
734 <latency>true</latency>
735 <timestamp>true</timestamp>
736 <success>true</success>
737 <label>true</label>
738 <code>true</code>
739 <message>true</message>
740 <threadName>true</threadName>
741 <dataType>true</dataType>
742 <encoding>false</encoding>
743 <assertions>false</assertions>
744 <subresults>false</subresults>
745 <responseData>false</responseData>
746 <samplerData>false</samplerData>
747 <xml>false</xml>
748 <fieldNames>true</fieldNames>
749 <responseHeaders>false</responseHeaders>
750 <requestHeaders>false</requestHeaders>
751 <responseDataOnError>false</responseDataOnError>
752 <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
753 <assertionsResultsToSave>0</assertionsResultsToSave>
754392 </value>
755393 </objProp>
756394 <stringProp name="filename"></stringProp>
784422 <assertionsResultsToSave>0</assertionsResultsToSave>
785423 <bytes>true</bytes>
786424 <sentBytes>true</sentBytes>
425 <url>true</url>
787426 <threadCounts>true</threadCounts>
788427 <idleTime>true</idleTime>
789428 <connectTime>true</connectTime>
790 </value>
791 </objProp>
792 <objProp>
793 <name></name>
794 <value class="SampleSaveConfiguration">
795 <time>true</time>
796 <latency>true</latency>
797 <timestamp>true</timestamp>
798 <success>true</success>
799 <label>true</label>
800 <code>true</code>
801 <message>true</message>
802 <threadName>true</threadName>
803 <dataType>true</dataType>
804 <encoding>false</encoding>
805 <assertions>true</assertions>
806 <subresults>true</subresults>
807 <responseData>false</responseData>
808 <samplerData>false</samplerData>
809 <xml>false</xml>
810 <fieldNames>false</fieldNames>
811 <responseHeaders>false</responseHeaders>
812 <requestHeaders>false</requestHeaders>
813 <responseDataOnError>false</responseDataOnError>
814 <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
815 <assertionsResultsToSave>0</assertionsResultsToSave>
816 <bytes>true</bytes>
817 </value>
818 </objProp>
819 <stringProp name="filename"></stringProp>
820 </ResultCollector>
821 <hashTree/>
822 <ResultCollector guiclass="RespTimeGraphVisualizer" testclass="ResultCollector" testname="Response Time Graph" enabled="true">
823 <boolProp name="ResultCollector.error_logging">false</boolProp>
824 <objProp>
825 <name>saveConfig</name>
826 <value class="SampleSaveConfiguration">
827 <time>true</time>
828 <latency>true</latency>
829 <timestamp>true</timestamp>
830 <success>true</success>
831 <label>true</label>
832 <code>true</code>
833 <message>true</message>
834 <threadName>true</threadName>
835 <dataType>true</dataType>
836 <encoding>false</encoding>
837 <assertions>true</assertions>
838 <subresults>true</subresults>
839 <responseData>false</responseData>
840 <samplerData>false</samplerData>
841 <xml>false</xml>
842 <fieldNames>true</fieldNames>
843 <responseHeaders>false</responseHeaders>
844 <requestHeaders>false</requestHeaders>
845 <responseDataOnError>false</responseDataOnError>
846 <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
847 <assertionsResultsToSave>0</assertionsResultsToSave>
848 <bytes>true</bytes>
849 <sentBytes>true</sentBytes>
850 <threadCounts>true</threadCounts>
851 <idleTime>true</idleTime>
852 <connectTime>true</connectTime>
853 </value>
854 </objProp>
855 <objProp>
856 <name></name>
857 <value class="SampleSaveConfiguration">
858 <time>true</time>
859 <latency>true</latency>
860 <timestamp>true</timestamp>
861 <success>true</success>
862 <label>true</label>
863 <code>true</code>
864 <message>true</message>
865 <threadName>true</threadName>
866 <dataType>true</dataType>
867 <encoding>false</encoding>
868 <assertions>true</assertions>
869 <subresults>true</subresults>
870 <responseData>false</responseData>
871 <samplerData>false</samplerData>
872 <xml>false</xml>
873 <fieldNames>false</fieldNames>
874 <responseHeaders>false</responseHeaders>
875 <requestHeaders>false</requestHeaders>
876 <responseDataOnError>false</responseDataOnError>
877 <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
878 <assertionsResultsToSave>0</assertionsResultsToSave>
879 <bytes>true</bytes>
880429 </value>
881430 </objProp>
882431 <stringProp name="filename"></stringProp>
0
1 LogLevel auth_openidc:debug
2
3 LoadModule auth_openidc_module /usr/lib/apache2/modules/mod_auth_openidc.so
4 OIDCProviderMetadataURL https://keycloak:8443/auth/realms/master/.well-known/openid-configuration
5
6 OIDCRedirectURI /protected/
7 OIDCSSLValidateServer Off
8 OIDCClientID web_client
9 OIDCClientSecret mysecret
10 OIDCCryptoPassphrase 91827364
11
12 OIDCInfoHook iat access_token access_token_expires id_token userinfo refresh_token session
13 OIDCScope "openid email profile"
14
15 <Location />
16 AuthType openid-connect
17 Require valid-user
18
19 ProxyPass http://echo/
20 ProxyPassReverse http://echo/
21 </Location>
22
23 OIDCOAuthSSLValidateServer Off
24 OIDCOAuthIntrospectionEndpoint https://keycloak:8443/auth/realms/master/protocol/openid-connect/token/introspect
25 OIDCOAuthClientID introspect_client
26 OIDCOAuthClientSecret mysecret
27 #OIDCOAuthVerifyJwksUri https://keycloak:8443/auth/realms/master/protocol/openid-connect/certs
28
29 <Location /api>
30 AuthType oauth20
31 Require valid-user
32 ProxyPass http://echo/headers
33 ProxyPassReverse http://echo/headers
34 </Location>
150150 return 0;
151151 }
152152
153 AP_DECLARE(void) ap_hook_insert_filter(request_rec *r) {
153 AP_DECLARE(void) ap_hook_insert_filter(struct request_rec *r) {
154154 }
155155
156156 AP_DECLARE(void) ap_hook_post_config(
4343
4444 #include <mod_auth_openidc.h>
4545
46 #include <openssl/rsa.h>
4746 #include <openssl/pem.h>
4847
4948 int usage(int argc, char **argv, const char *msg) {
5049 fprintf(stderr, "Usage: %s %s\n", argv[0],
51 msg ? msg : "[ sign | verify | decrypt | jwk2cert | key2jwk | enckey | hash_base64url | timestamp | uuid ] <options>");
50 msg ? msg : "[ sign | verify | decrypt | key2jwk | enckey | hash_base64url | timestamp | uuid ] <options>");
5251 return -1;
5352 }
5453
243242
244243 fprintf(stdout, "%s", plaintext);
245244 oidc_jwk_destroy(jwk);
246
247 return 0;
248 }
249
250
251 int mkcert(RSA *rsa, X509 **x509p, EVP_PKEY **pkeyp, int serial, int days) {
252 X509 *x;
253 EVP_PKEY *pk;
254 X509_NAME *name = NULL;
255
256 if ((pkeyp == NULL) || (*pkeyp == NULL)) {
257 if ((pk = EVP_PKEY_new()) == NULL)
258 return -1;
259 } else
260 pk = *pkeyp;
261
262 if ((x509p == NULL) || (*x509p == NULL)) {
263 if ((x = X509_new()) == NULL)
264 return -1;
265 } else
266 x = *x509p;
267
268 if (!EVP_PKEY_assign_RSA(pk, rsa))
269 return -1;
270
271 X509_set_version(x, 2);
272 ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
273 X509_gmtime_adj(X509_get_notBefore(x), 0);
274 X509_gmtime_adj(X509_get_notAfter(x), (long) 60 * 60 * 24 * days);
275 X509_set_pubkey(x, pk);
276
277 name = X509_get_subject_name(x);
278
279 X509_NAME_add_entry_by_txt(name, "C",
280 MBSTRING_ASC, (const unsigned char *) "NL", -1, -1, 0);
281 X509_NAME_add_entry_by_txt(name, "CN",
282 MBSTRING_ASC, (const unsigned char *) "Ping Identity", -1, -1, 0);
283
284 X509_set_issuer_name(x, name);
285
286 if (!X509_sign(x, pk, EVP_md5()))
287 return -1;
288
289 *x509p = x;
290 *pkeyp = pk;
291
292 return 0;
293 }
294
295 int jwk2cert(int argc, char **argv, apr_pool_t *pool) {
296
297 if (argc <= 2)
298 return usage(argc, argv, "jwk2cert <jwk-file>");
299
300 char *s_jwk = NULL;
301
302 if (file_read(pool, argv[2], &s_jwk) != 0)
303 return -1;
304
305 cjose_err cjose_err;
306
307 cjose_jwk_t *jwk = cjose_jwk_import(s_jwk, strlen(s_jwk), &cjose_err);
308 if (jwk == NULL) {
309 fprintf(stderr,
310 "could not import JWK: %s [file: %s, function: %s, line: %ld]\n",
311 cjose_err.message, cjose_err.file, cjose_err.function,
312 cjose_err.line);
313 return -1;
314 }
315
316 if (cjose_jwk_get_kty(jwk, &cjose_err) != CJOSE_JWK_KTY_RSA) {
317 fprintf(stderr, "wrong key type");
318 return -1;
319 }
320
321 RSA *rsa = cjose_jwk_get_keydata(jwk, &cjose_err);
322 //PEM_write_RSAPublicKey(stdout, rsa);
323 PEM_write_RSA_PUBKEY(stdout, rsa);
324
325 X509 *x509 = NULL;
326 EVP_PKEY *pkey = NULL;
327
328 if (mkcert(rsa, &x509, &pkey, 0, 365) != 0)
329 return -1;
330
331 //RSA_print_fp(stdout,pkey->pkey.rsa,0);
332 //X509_print_fp(stdout,x509);
333
334 //PEM_write_PrivateKey(stdout,pkey,NULL,NULL,0,NULL, NULL);
335 PEM_write_X509(stdout, x509);
336
337 X509_free(x509);
338 EVP_PKEY_free(pkey);
339245
340246 return 0;
341247 }
599505 if (strcmp(argv[1], "decrypt") == 0)
600506 return decrypt(argc, argv, pool);
601507
602 if (strcmp(argv[1], "jwk2cert") == 0)
603 return jwk2cert(argc, argv, pool);
604
605508 if (strcmp(argv[1], "key2jwk") == 0)
606509 return key2jwk(argc, argv, pool);
607510
17301730 request->server->process = apr_pcalloc(request->pool,
17311731 sizeof(struct process_rec));
17321732 request->server->process->pool = request->pool;
1733 request->server->process->pconf = request->pool;
17331734 request->connection = apr_pcalloc(request->pool, sizeof(struct conn_rec));
17341735 request->connection->bucket_alloc = apr_bucket_alloc_create(request->pool);
17351736 request->connection->local_addr = apr_pcalloc(request->pool,
0 #!/bin/bash
1
2 # need to forward SIGTERM to child process that runs Valgrind
3 _term() {
4 echo "Caught SIGTERM signal!"
5 kill -TERM "$child" 2>/dev/null
6 }
7 trap _term SIGTERM
8
9 a2enconf openidc
10 source /etc/apache2/envvars
11
12 valgrind \
13 --leak-check=full \
14 --error-exitcode=1 \
15 --show-possibly-lost=no \
16 --read-inline-info=yes \
17 --keep-debuginfo=yes \
18 --undef-value-errors=no \
19 --log-file=/tmp/valgrind.log \
20 /usr/sbin/apache2 -X &
21
22 child=$!
23 wait "$child"
24
25 # wait until the logfile has been written and closed...
26 while ! tail -n 25 /tmp/valgrind.log | grep "ERROR SUMMARY" > /dev/null ; do sleep 1; done
27 # print results and summary
28 cat /tmp/valgrind.log
29 # verify that there are no memory leaks found
30 grep -A1 "LEAK SUMMARY" /tmp/valgrind.log | grep -q "definitely lost: 0 bytes in 0 blocks"