@continuoussecuritytooling/keycloak-reporter 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +4 -3
- package/.github/workflows/pipeline.yml +37 -10
- package/.github/workflows/release.yml +1 -1
- package/.prettierrc +2 -2
- package/Dockerfile +15 -1
- package/README.md +4 -3
- package/artifacthub-repo.yml +6 -0
- package/charts/keycloak-reporter/Chart.yaml +9 -3
- package/charts/keycloak-reporter/README.md +7 -16
- package/charts/keycloak-reporter/values.yaml +2 -1
- package/cli.ts +52 -87
- package/config/schema.json +6 -1
- package/index.ts +1 -1
- package/lib/client.ts +10 -37
- package/lib/output.ts +2 -2
- package/lib/user.ts +86 -49
- package/package.json +4 -3
- package/renovate.json +12 -5
- package/src/commands.ts +27 -0
- package/src/config.ts +6 -18
- package/dist/cli.js +0 -131
- package/dist/cli.js.map +0 -1
- package/dist/config/schema.json +0 -65
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -1
- package/dist/lib/client.js +0 -41
- package/dist/lib/client.js.map +0 -1
- package/dist/lib/convert.js +0 -9
- package/dist/lib/convert.js.map +0 -1
- package/dist/lib/output.js +0 -113
- package/dist/lib/output.js.map +0 -1
- package/dist/lib/user.js +0 -75
- package/dist/lib/user.js.map +0 -1
- package/dist/src/cli.js +0 -19
- package/dist/src/cli.js.map +0 -1
- package/dist/src/config.js +0 -57
- package/dist/src/config.js.map +0 -1
- package/src/cli.ts +0 -26
package/.eslintrc.cjs
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
module.exports = {
|
|
3
3
|
env: {
|
|
4
4
|
node: true,
|
|
5
|
-
commonjs: true
|
|
5
|
+
commonjs: true,
|
|
6
6
|
},
|
|
7
7
|
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
|
8
8
|
parser: '@typescript-eslint/parser',
|
|
9
9
|
plugins: ['@typescript-eslint'],
|
|
10
10
|
root: true,
|
|
11
11
|
rules: {
|
|
12
|
-
quotes: [2, 'single', { avoidEscape: true }]
|
|
13
|
-
|
|
12
|
+
quotes: [2, 'single', { avoidEscape: true }],
|
|
13
|
+
'comma-dangle': ['error', 'only-multiline'],
|
|
14
|
+
},
|
|
14
15
|
};
|
|
@@ -6,6 +6,8 @@ on:
|
|
|
6
6
|
push:
|
|
7
7
|
branches:
|
|
8
8
|
- develop
|
|
9
|
+
tags:
|
|
10
|
+
- '*'
|
|
9
11
|
|
|
10
12
|
jobs:
|
|
11
13
|
build:
|
|
@@ -23,7 +25,7 @@ jobs:
|
|
|
23
25
|
steps:
|
|
24
26
|
- uses: actions/checkout@v4
|
|
25
27
|
- name: 'Use Node.js ${{ matrix.node_version }}'
|
|
26
|
-
uses: actions/setup-node@
|
|
28
|
+
uses: actions/setup-node@v4
|
|
27
29
|
with:
|
|
28
30
|
node-version: '${{ matrix.node_version }}'
|
|
29
31
|
- name: npm build and test
|
|
@@ -53,7 +55,7 @@ jobs:
|
|
|
53
55
|
check-latest: true
|
|
54
56
|
|
|
55
57
|
- name: Helm Chart Testing
|
|
56
|
-
uses: helm/chart-testing-action@v2.
|
|
58
|
+
uses: helm/chart-testing-action@v2.6.0
|
|
57
59
|
|
|
58
60
|
- name: Run chart-testing (list-changed)
|
|
59
61
|
id: list-changed
|
|
@@ -92,7 +94,7 @@ jobs:
|
|
|
92
94
|
steps:
|
|
93
95
|
- uses: actions/checkout@v4
|
|
94
96
|
- name: 'Use Node.js ${{ matrix.node_version }}'
|
|
95
|
-
uses: actions/setup-node@
|
|
97
|
+
uses: actions/setup-node@v4
|
|
96
98
|
with:
|
|
97
99
|
node-version: '${{ matrix.node_version }}'
|
|
98
100
|
- name: Install Java
|
|
@@ -131,24 +133,38 @@ jobs:
|
|
|
131
133
|
- end2end
|
|
132
134
|
steps:
|
|
133
135
|
- uses: actions/checkout@v4
|
|
134
|
-
- uses: actions/setup-node@
|
|
135
|
-
# TODO: Support Node 16+
|
|
136
|
+
- uses: actions/setup-node@v4
|
|
136
137
|
with:
|
|
137
|
-
|
|
138
|
+
# renovate: datasource=docker depName=node
|
|
139
|
+
node-version: '18'
|
|
138
140
|
- name: 'Build Package'
|
|
139
141
|
run: |
|
|
140
142
|
npm run clean
|
|
141
143
|
npm run build
|
|
142
|
-
|
|
144
|
+
|
|
145
|
+
- name: Write version vars
|
|
146
|
+
run: |
|
|
147
|
+
BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"`
|
|
148
|
+
VERSION=${GITHUB_REF_NAME#v}
|
|
149
|
+
echo Version: $VERSION
|
|
150
|
+
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
|
151
|
+
echo "APP_VERSION=$VERSION" >> $GITHUB_ENV
|
|
152
|
+
echo "BUILD_DATE=$BUILD_DATE" >> $GITHUB_ENV
|
|
153
|
+
|
|
154
|
+
- name: Build Container Image
|
|
143
155
|
id: build-image
|
|
144
156
|
uses: redhat-actions/buildah-build@v2
|
|
145
157
|
with:
|
|
146
158
|
image: continuoussecuritytooling/keycloak-reporting-cli
|
|
147
|
-
tags: '
|
|
159
|
+
tags: 'rc_build ${{ github.sha }}'
|
|
148
160
|
containerfiles: |
|
|
149
161
|
./Dockerfile
|
|
162
|
+
build-args: |
|
|
163
|
+
BUILD_DATE=${{env.BUILD_DATE}}
|
|
164
|
+
APP_VERSION=${{env.APP_VERSION}}
|
|
165
|
+
|
|
150
166
|
- name: Push To Docker Hub
|
|
151
|
-
id: push-to-dockerhub
|
|
167
|
+
id: push-to-dockerhub-preview
|
|
152
168
|
uses: redhat-actions/push-to-registry@v2
|
|
153
169
|
with:
|
|
154
170
|
image: ${{ steps.build-image.outputs.image }}
|
|
@@ -156,4 +172,15 @@ jobs:
|
|
|
156
172
|
registry: registry.hub.docker.com
|
|
157
173
|
username: continuoussecuritytooling
|
|
158
174
|
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
|
159
|
-
if: github.ref == 'refs/heads/develop'
|
|
175
|
+
if: github.ref == 'refs/heads/develop'
|
|
176
|
+
|
|
177
|
+
- name: Push To Docker Hub
|
|
178
|
+
id: push-to-dockerhub-tagged
|
|
179
|
+
uses: redhat-actions/push-to-registry@v2
|
|
180
|
+
with:
|
|
181
|
+
image: ${{ steps.build-image.outputs.image }}
|
|
182
|
+
tags: latest ${VERSION}
|
|
183
|
+
registry: registry.hub.docker.com
|
|
184
|
+
username: continuoussecuritytooling
|
|
185
|
+
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
|
186
|
+
if: github.ref_type == 'tag'
|
package/.prettierrc
CHANGED
package/Dockerfile
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
FROM node:18
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ARG BUILD_DATE
|
|
4
|
+
ARG APP_VERSION
|
|
5
|
+
|
|
6
|
+
LABEL org.opencontainers.image.authors='Martin Reinhardt (martin@m13t.de)' \
|
|
7
|
+
org.opencontainers.image.created=$BUILD_DATE \
|
|
8
|
+
org.opencontainers.image.version=$APP_VERSION \
|
|
9
|
+
org.opencontainers.image.url='https://hub.docker.com/r/continuoussecuritytooling/keycloak-reporting-cli' \
|
|
10
|
+
org.opencontainers.image.documentation='https://github.com/ContinuousSecurityTooling/keycloak-reporter' \
|
|
11
|
+
org.opencontainers.image.source='https://github.com/ContinuousSecurityTooling/keycloak-reporter.git' \
|
|
12
|
+
org.opencontainers.image.licenses='MIT'
|
|
4
13
|
|
|
5
14
|
ENV CONFIG_FILE=/app/config.json
|
|
6
15
|
|
|
@@ -11,6 +20,11 @@ WORKDIR /app
|
|
|
11
20
|
RUN cd /app && npm install --omit=dev &&\
|
|
12
21
|
chown -R 1000:2000 /app
|
|
13
22
|
|
|
23
|
+
# apt update
|
|
24
|
+
RUN apt-get update && apt-get -y upgrade &&\
|
|
25
|
+
# clean up to slim image
|
|
26
|
+
apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/
|
|
27
|
+
|
|
14
28
|
USER 1000
|
|
15
29
|
|
|
16
30
|
ENTRYPOINT ["/app/docker_entrypoint.sh"]
|
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Keycloak Reporter
|
|
2
2
|
|
|
3
|
+
Keycloak user and client reporting tool for automated regular access checks.
|
|
3
4
|
|
|
4
5
|
[](LICENSE)
|
|
5
6
|
[](https://github.com/ContinuousSecurityTooling/keycloak-reporter/actions/workflows/pipeline.yml)
|
|
@@ -7,8 +8,8 @@
|
|
|
7
8
|
[](https://www.npmjs.com/package/@continuoussecuritytooling/keycloak-reporter)
|
|
8
9
|
[](https://hub.docker.com/r/continuoussecuritytooling/keycloak-reporting-cli/)
|
|
9
10
|
[](https://snyk.io/test/github/ContinuousSecurityTooling/keycloak-reporter)
|
|
10
|
-
|
|
11
11
|
[](https://hub.docker.com/r/continuoussecuritytooling/keycloak-reporting-cli/)
|
|
12
|
+
[](https://artifacthub.io/packages/helm/keycloak-reporter/keycloak-reporter)
|
|
12
13
|
|
|
13
14
|
## Usage
|
|
14
15
|
|
|
@@ -58,10 +59,10 @@ Valid commands are:
|
|
|
58
59
|
|
|
59
60
|
### Helm
|
|
60
61
|
|
|
61
|
-
To install the Helm Chart use the OCI Package:
|
|
62
|
+
To install the Helm Chart use the [OCI Package Registry](https://github.com/orgs/CloudTooling/packages):
|
|
62
63
|
|
|
63
64
|
```
|
|
64
|
-
helm install keycloak-reporter oci://cloudtooling/helm-charts
|
|
65
|
+
helm install keycloak-reporter oci://ghcr.io/cloudtooling/helm-charts
|
|
65
66
|
```
|
|
66
67
|
|
|
67
68
|
### Config file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
apiVersion: v2
|
|
2
2
|
name: keycloak-reporter
|
|
3
|
-
description:
|
|
3
|
+
description: Keycloak user and client reporting tool for automated regular access checks.
|
|
4
4
|
|
|
5
5
|
# A chart can be either an 'application' or a 'library' chart.
|
|
6
6
|
#
|
|
@@ -15,15 +15,21 @@ type: application
|
|
|
15
15
|
# This is the chart version. This version number should be incremented each time you make changes
|
|
16
16
|
# to the chart and its templates, including the app version.
|
|
17
17
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
|
18
|
-
version: 1.
|
|
18
|
+
version: 1.1.0
|
|
19
19
|
|
|
20
20
|
# This is the version number of the application being deployed. This version number should be
|
|
21
21
|
# incremented each time you make changes to the application. Versions are not expected to
|
|
22
22
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
|
23
23
|
# It is recommended to use it with quotes.
|
|
24
24
|
# renovate: datasource=github-tags depName=ContinuousSecurityTooling/keycloak-reporter
|
|
25
|
-
appVersion:
|
|
25
|
+
appVersion: '0.6.0'
|
|
26
26
|
maintainers:
|
|
27
27
|
# Martin Reinhardt
|
|
28
28
|
- name: hypery2k
|
|
29
29
|
email: martin@m13t.de
|
|
30
|
+
annotations:
|
|
31
|
+
artifacthub.io/links: |
|
|
32
|
+
- name: GitHub
|
|
33
|
+
url: https://github.com/ContinuousSecurityTooling/keycloak-reporter
|
|
34
|
+
- name: Keycloak Auditor
|
|
35
|
+
url: https://github.com/ContinuousSecurityTooling/keycloak-auditor
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# keycloak-reporter
|
|
2
2
|
|
|
3
|
-
  
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Keycloak user and client reporting tool for automated regular access checks.
|
|
6
6
|
|
|
7
7
|
## Maintainers
|
|
8
8
|
|
|
@@ -15,32 +15,23 @@ A Helm chart for Kubernetes
|
|
|
15
15
|
| Key | Type | Default | Description |
|
|
16
16
|
|-----|------|---------|-------------|
|
|
17
17
|
| affinity | object | `{}` | |
|
|
18
|
-
| cronjobs
|
|
19
|
-
|
|
|
20
|
-
| env | object | `{}` | |
|
|
18
|
+
| cronjobs | map | `{"clients":"0 0 1 */3 *","users":"0 0 1 */3 *"}` | Cron configuration |
|
|
19
|
+
| env | map | `{}` | additonal environment variables |
|
|
21
20
|
| fullnameOverride | string | `""` | |
|
|
22
21
|
| image.pullPolicy | string | `"IfNotPresent"` | |
|
|
23
22
|
| image.repository | string | `"continuoussecuritytooling/keycloak-reporting-cli"` | |
|
|
23
|
+
| image.tag | string | `""` | |
|
|
24
24
|
| imagePullSecrets | list | `[]` | |
|
|
25
|
-
| keycloak
|
|
26
|
-
| keycloak.config.clientSecret | string | `""` | |
|
|
27
|
-
| keycloak.config.output | string | `"webhook"` | |
|
|
28
|
-
| keycloak.config.url | string | `""` | |
|
|
25
|
+
| keycloak | map | `{"config":{"clientId":"","clientSecret":"","output":"webhook","url":"","useAuditingEndpoint":false,"webhookMessage":"","webhookType":"","webhookUrl":""},"volumes":{"reports":""}}` | Keycloak configuration |
|
|
29
26
|
| keycloak.config.webhookMessage | string | `""` | optional message for the webhook post |
|
|
30
|
-
| keycloak.config.webhookType | string | `""` | |
|
|
31
|
-
| keycloak.config.webhookUrl | string | `""` | |
|
|
32
|
-
| keycloak.volumes.reports | string | `""` | |
|
|
33
27
|
| nameOverride | string | `""` | |
|
|
34
28
|
| nodeSelector | object | `{}` | |
|
|
35
29
|
| podAnnotations | object | `{}` | |
|
|
36
|
-
| podSecurityContext | object | `{}` | |
|
|
37
30
|
| replicaCount | int | `1` | |
|
|
38
|
-
| resources | object | `{}` | |
|
|
39
|
-
| securityContext | object | `{}` | |
|
|
40
31
|
| serviceAccount.annotations | object | `{}` | |
|
|
41
32
|
| serviceAccount.create | bool | `true` | |
|
|
42
33
|
| serviceAccount.name | string | `""` | |
|
|
43
34
|
| tolerations | list | `[]` | |
|
|
44
35
|
|
|
45
36
|
----------------------------------------------
|
|
46
|
-
Autogenerated from chart metadata using [helm-docs v1.11.
|
|
37
|
+
Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3)
|
|
@@ -8,7 +8,7 @@ image:
|
|
|
8
8
|
repository: continuoussecuritytooling/keycloak-reporting-cli
|
|
9
9
|
pullPolicy: IfNotPresent
|
|
10
10
|
# Overrides the image tag whose default is the chart appVersion.
|
|
11
|
-
|
|
11
|
+
tag: ""
|
|
12
12
|
|
|
13
13
|
imagePullSecrets: []
|
|
14
14
|
nameOverride: ''
|
|
@@ -51,6 +51,7 @@ keycloak:
|
|
|
51
51
|
output: 'webhook'
|
|
52
52
|
webhookType: ''
|
|
53
53
|
webhookUrl: ''
|
|
54
|
+
useAuditingEndpoint: false
|
|
54
55
|
# -- optional message for the webhook post
|
|
55
56
|
webhookMessage: ''
|
|
56
57
|
volumes:
|
package/cli.ts
CHANGED
|
@@ -4,15 +4,8 @@ import { writeFileSync } from 'node:fs';
|
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import yargs from 'yargs/yargs';
|
|
6
6
|
import { hideBin } from 'yargs/helpers';
|
|
7
|
-
import {
|
|
8
|
-
listUsers,
|
|
9
|
-
listClients,
|
|
10
|
-
Options,
|
|
11
|
-
convertJSON2CSV,
|
|
12
|
-
post2Webhook
|
|
13
|
-
} from './index.js';
|
|
7
|
+
import { listUsers, listClients, Options, convertJSON2CSV, post2Webhook } from './index.js';
|
|
14
8
|
import config from './src/config.js';
|
|
15
|
-
|
|
16
9
|
class WebhookConfig {
|
|
17
10
|
type: string;
|
|
18
11
|
url: string;
|
|
@@ -31,13 +24,34 @@ class ReportConfig {
|
|
|
31
24
|
directory: string;
|
|
32
25
|
}
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
27
|
+
function getKeycloakConfig(config, argv): Options {
|
|
28
|
+
return {
|
|
29
|
+
clientId: config.clientId ? config.clientId : (argv.clientId as string),
|
|
30
|
+
clientSecret: config.clientSecret ? config.clientSecret : (argv.clientSecret as string),
|
|
31
|
+
rootUrl: config.url ? config.url : (argv.url as string),
|
|
32
|
+
useAuditingEndpoint: argv.useAuditingEndpoint == true || config.useAuditingEndpoint.toLowerCase() == 'true',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function convertData(config, argv, name: string, title: string, json: object) {
|
|
37
|
+
convert(
|
|
38
|
+
config.format ? config.format : (argv.format as string),
|
|
39
|
+
config.output ? config.output : (argv.output as string),
|
|
40
|
+
{
|
|
41
|
+
name,
|
|
42
|
+
directory: argv.reports ? (argv.reports as string) : config.reports,
|
|
43
|
+
},
|
|
44
|
+
new WebhookConfig(
|
|
45
|
+
config.webhookType ? config.webhookType : (argv.webhookType as string),
|
|
46
|
+
config.webhookUrl ? config.webhookUrl : (argv.webhookUrl as string),
|
|
47
|
+
title,
|
|
48
|
+
config.webhookMessage ? config.webhookMessage : (argv.webhookMessage as string)
|
|
49
|
+
),
|
|
50
|
+
json
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function convert(format: string, output: string, reports: ReportConfig, config: WebhookConfig, json: object) {
|
|
41
55
|
let outputContent: string;
|
|
42
56
|
switch (format) {
|
|
43
57
|
case 'csv':
|
|
@@ -52,24 +66,20 @@ async function convert(
|
|
|
52
66
|
writeFileSync(
|
|
53
67
|
path.join(
|
|
54
68
|
`${reports.directory}`,
|
|
55
|
-
`${reports.name}_${date.getFullYear()}-${
|
|
56
|
-
date.getMonth() + 1
|
|
57
|
-
}-${date.getDate()}.${format.toLowerCase()}`
|
|
69
|
+
`${reports.name}_${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}.${format.toLowerCase()}`
|
|
58
70
|
),
|
|
59
71
|
outputContent
|
|
60
72
|
);
|
|
61
73
|
}
|
|
62
74
|
switch (output) {
|
|
63
75
|
case 'webhook':
|
|
76
|
+
if (!config.url) {
|
|
77
|
+
console.error('No valid Webhook URL given');
|
|
78
|
+
throw new Error('Please provide a valid --webhookUrl parameter');
|
|
79
|
+
}
|
|
64
80
|
try {
|
|
65
81
|
console.log(`Sending report via webhook to ${config.type} ....`);
|
|
66
|
-
await post2Webhook(
|
|
67
|
-
config.type,
|
|
68
|
-
config.url,
|
|
69
|
-
config.title,
|
|
70
|
-
outputContent,
|
|
71
|
-
config.message
|
|
72
|
-
);
|
|
82
|
+
await post2Webhook(config.type, config.url, config.title, outputContent, config.message);
|
|
73
83
|
console.log('Done sending.');
|
|
74
84
|
} catch (e) {
|
|
75
85
|
switch (e.code || e.message) {
|
|
@@ -80,10 +90,7 @@ async function convert(
|
|
|
80
90
|
console.error('Invalid Slack Webhook Payload. Check your params.');
|
|
81
91
|
throw new Error('Invalid Slack Payload');
|
|
82
92
|
default:
|
|
83
|
-
console.error(
|
|
84
|
-
`Error during sending webhook.(${e?.code})`,
|
|
85
|
-
e?.original
|
|
86
|
-
);
|
|
93
|
+
console.error(`Error during sending webhook.(${e?.code})`, e?.original);
|
|
87
94
|
throw e;
|
|
88
95
|
}
|
|
89
96
|
}
|
|
@@ -101,32 +108,8 @@ yargs(hideBin(process.argv))
|
|
|
101
108
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
102
109
|
() => {},
|
|
103
110
|
async (argv) => {
|
|
104
|
-
const users = await listUsers(
|
|
105
|
-
|
|
106
|
-
clientSecret: config.clientSecret
|
|
107
|
-
? config.clientSecret
|
|
108
|
-
: (argv.clientSecret as string),
|
|
109
|
-
rootUrl: config.url ? config.url : (argv.url as string)
|
|
110
|
-
});
|
|
111
|
-
await convert(
|
|
112
|
-
config.format ? config.format : (argv.format as string),
|
|
113
|
-
config.output ? config.output : (argv.output as string),
|
|
114
|
-
{
|
|
115
|
-
name: 'user_listing',
|
|
116
|
-
directory: argv.reports ? (argv.reports as string) : config.reports
|
|
117
|
-
},
|
|
118
|
-
new WebhookConfig(
|
|
119
|
-
config.webhookType
|
|
120
|
-
? config.webhookType
|
|
121
|
-
: (argv.webhookType as string),
|
|
122
|
-
config.webhookUrl ? config.webhookUrl : (argv.webhookUrl as string),
|
|
123
|
-
'User Listing',
|
|
124
|
-
config.webhookMessage
|
|
125
|
-
? config.webhookMessage
|
|
126
|
-
: (argv.webhookMessage as string)
|
|
127
|
-
),
|
|
128
|
-
users
|
|
129
|
-
);
|
|
111
|
+
const users = await listUsers(getKeycloakConfig(config, argv));
|
|
112
|
+
convertData(config, argv, 'user_listing', 'User Listing', users);
|
|
130
113
|
}
|
|
131
114
|
)
|
|
132
115
|
.command(
|
|
@@ -135,65 +118,47 @@ yargs(hideBin(process.argv))
|
|
|
135
118
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
136
119
|
() => {},
|
|
137
120
|
async (argv) => {
|
|
138
|
-
const clients = await listClients(
|
|
139
|
-
|
|
140
|
-
clientSecret: config.clientSecret
|
|
141
|
-
? config.clientSecret
|
|
142
|
-
: (argv.clientSecret as string),
|
|
143
|
-
rootUrl: config.url ? config.url : (argv.url as string)
|
|
144
|
-
});
|
|
145
|
-
await convert(
|
|
146
|
-
config.format ? config.format : (argv.format as string),
|
|
147
|
-
config.output ? config.output : (argv.output as string),
|
|
148
|
-
{
|
|
149
|
-
name: 'client_listing',
|
|
150
|
-
directory: argv.reports ? (argv.reports as string) : config.reports
|
|
151
|
-
},
|
|
152
|
-
new WebhookConfig(
|
|
153
|
-
config.webhookType
|
|
154
|
-
? config.webhookType
|
|
155
|
-
: (argv.webhookType as string),
|
|
156
|
-
config.webhookUrl ? config.webhookUrl : (argv.webhookUrl as string),
|
|
157
|
-
'Client Listing',
|
|
158
|
-
config.webhookMessage
|
|
159
|
-
? config.webhookMessage
|
|
160
|
-
: (argv.webhookMessage as string)
|
|
161
|
-
),
|
|
162
|
-
clients
|
|
163
|
-
);
|
|
121
|
+
const clients = await listClients(getKeycloakConfig(config, argv));
|
|
122
|
+
convertData(config, argv, 'client_listing', 'Client Listing', clients);
|
|
164
123
|
}
|
|
165
124
|
)
|
|
166
125
|
.option('format', {
|
|
167
126
|
alias: 'f',
|
|
168
127
|
type: 'string',
|
|
169
128
|
default: 'json',
|
|
170
|
-
description: 'output format, e.g. JSON|CSV'
|
|
129
|
+
description: 'output format, e.g. JSON|CSV',
|
|
171
130
|
})
|
|
172
131
|
.option('output', {
|
|
173
132
|
alias: 'o',
|
|
174
133
|
type: 'string',
|
|
175
134
|
default: 'stdout',
|
|
176
|
-
description: 'output channel'
|
|
135
|
+
description: 'output channel',
|
|
177
136
|
})
|
|
178
137
|
.option('webhookType', {
|
|
179
138
|
alias: 'w',
|
|
180
139
|
type: 'string',
|
|
181
140
|
default: 'slack',
|
|
182
|
-
description: 'Webhook Type'
|
|
141
|
+
description: 'Webhook Type',
|
|
183
142
|
})
|
|
184
143
|
.option('webhookMessage', {
|
|
185
144
|
alias: 'm',
|
|
186
145
|
type: 'string',
|
|
187
|
-
description: 'Webhook Message'
|
|
146
|
+
description: 'Webhook Message',
|
|
188
147
|
})
|
|
189
148
|
.option('webhookUrl', {
|
|
190
149
|
alias: 't',
|
|
191
150
|
type: 'string',
|
|
192
|
-
description: 'Webhook URL'
|
|
151
|
+
description: 'Webhook URL',
|
|
193
152
|
})
|
|
194
153
|
.option('reports', {
|
|
195
154
|
alias: 'r',
|
|
196
155
|
type: 'string',
|
|
197
|
-
description: 'Reports directory'
|
|
156
|
+
description: 'Reports directory',
|
|
157
|
+
})
|
|
158
|
+
.option('useAuditingEndpoint', {
|
|
159
|
+
alias: 'a',
|
|
160
|
+
type: 'boolean',
|
|
161
|
+
default: false,
|
|
162
|
+
description: 'use auditior rest endpoint',
|
|
198
163
|
})
|
|
199
164
|
.parse();
|
package/config/schema.json
CHANGED
package/index.ts
CHANGED
package/lib/client.ts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import { Issuer } from 'openid-client';
|
|
2
1
|
import KcAdminClient from '@keycloak/keycloak-admin-client';
|
|
3
|
-
|
|
4
|
-
// Token refresh interval 60 seconds
|
|
5
|
-
const TOKEN_REFRESH = 60;
|
|
2
|
+
import { AuditClient } from '@continuoussecuritytooling/keycloak-auditor';
|
|
6
3
|
|
|
7
4
|
export interface Options {
|
|
8
5
|
clientId: string;
|
|
9
6
|
clientSecret: string;
|
|
10
7
|
rootUrl: string;
|
|
8
|
+
useAuditingEndpoint: boolean;
|
|
11
9
|
}
|
|
12
10
|
|
|
13
|
-
export async function createClient(options: Options): Promise<KcAdminClient> {
|
|
14
|
-
const kcAdminClient =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
export async function createClient(options: Options): Promise<KcAdminClient | AuditClient> {
|
|
12
|
+
const kcAdminClient = options.useAuditingEndpoint
|
|
13
|
+
? new AuditClient(options.rootUrl, 'master')
|
|
14
|
+
: new KcAdminClient({
|
|
15
|
+
baseUrl: options.rootUrl,
|
|
16
|
+
realmName: 'master',
|
|
17
|
+
});
|
|
19
18
|
try {
|
|
20
19
|
// client login
|
|
21
20
|
await kcAdminClient.auth({
|
|
@@ -24,35 +23,9 @@ export async function createClient(options: Options): Promise<KcAdminClient> {
|
|
|
24
23
|
grantType: 'client_credentials',
|
|
25
24
|
});
|
|
26
25
|
} catch (e) {
|
|
27
|
-
console.error(
|
|
28
|
-
'Check Client Config:',
|
|
29
|
-
e.response ? e.response.data.error_description : e
|
|
30
|
-
);
|
|
26
|
+
console.error('Check Client Config:', e.response ? e.response.data.error_description : e);
|
|
31
27
|
return Promise.reject();
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
const keycloakIssuer = await Issuer.discover(
|
|
35
|
-
`${options.rootUrl}/realms/master`
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const client = new keycloakIssuer.Client({
|
|
39
|
-
client_id: options.clientId,
|
|
40
|
-
token_endpoint_auth_method: 'none', // to send only client_id in the header
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Use the grant type 'password'
|
|
44
|
-
const tokenSet = await client.grant({
|
|
45
|
-
client_id: options.clientId,
|
|
46
|
-
client_secret: options.clientSecret,
|
|
47
|
-
grant_type: 'client_credentials',
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
/*
|
|
51
|
-
// TODO: FIXME - Periodically using refresh_token grant flow to get new access token here
|
|
52
|
-
setInterval(async () => {
|
|
53
|
-
const refreshToken = tokenSet.refresh_token;
|
|
54
|
-
kcAdminClient.setAccessToken((await client.refresh(refreshToken)).access_token);
|
|
55
|
-
}, TOKEN_REFRESH * 1000); */
|
|
56
|
-
|
|
57
30
|
return new Promise((resolve) => resolve(kcAdminClient));
|
|
58
31
|
}
|
package/lib/output.ts
CHANGED
|
@@ -29,7 +29,7 @@ export async function post2Webhook(
|
|
|
29
29
|
{
|
|
30
30
|
contentType: 'application/vnd.microsoft.card.adaptive',
|
|
31
31
|
content: {
|
|
32
|
-
$schema: '
|
|
32
|
+
$schema: 'https://adaptivecards.io/schemas/adaptive-card.json',
|
|
33
33
|
type: 'AdaptiveCard',
|
|
34
34
|
version: '1.2',
|
|
35
35
|
body: [
|
|
@@ -68,7 +68,7 @@ export async function post2Webhook(
|
|
|
68
68
|
}
|
|
69
69
|
],
|
|
70
70
|
$schema:
|
|
71
|
-
'
|
|
71
|
+
'https://adaptivecards.io/schemas/adaptive-card.json'
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
]
|