Skip to content

Commit 9d037df

Browse files
lavocattMsarawan
authored andcommitted
[#5] don't skip tls checks
The jolokia api server will now check the the TLS cert of the broker when the connection is secured. In order to do so, at deploy time, a cluster issuer gets created by the script. This cluster issuer needs to be used to generate the cert the broker would use for its console. An example for a broker called ex-aao within the default namespace would be: ``` apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: ex-aao-console-certificate-cert namespace: default spec: secretName: ex-aao-console-certificate-cert-secret privateKey: algorithm: RSA encoding: PKCS1 size: 2048 isCA: false commonName: ex-aao-console-cert dnsNames: - ex-aao-wconsj-0-svc-rte-default.apps-crc.testing - ex-aao-wconsj-0-svc.default issuerRef: name: jolokia-api-server-selfsigned-issuer kind: ClusterIssuer group: cert-manager.io ``` When running in dev mode, if the broker is secured by TLS you'll also need the trust bundle to connect to it. To do so checkout the README instructions.
1 parent af3180b commit 9d037df

File tree

11 files changed

+213
-80
lines changed

11 files changed

+213
-80
lines changed

.env

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
PLUGIN_VERSION=0.1.2
32
PLUGIN_NAME='ActiveMQ Artemis Jolokia api-server'
43

@@ -9,13 +8,3 @@ SERVER_KEY=/var/serving-cert/tls.key
98
# logging
109
LOG_LEVEL='info'
1110
ENABLE_REQUEST_LOG='false'
12-
13-
# security
14-
15-
# replace the token in production deployment
16-
SECRET_ACCESS_TOKEN=1e13d44f998dee277deae621a9012cf300b94c91
17-
18-
API_SERVER_SECURITY_ENABLED=true
19-
API_SERVER_SECURITY_AUTH_TYPE=jwt
20-
USERS_FILE_URL=.users.json
21-
ENDPOINTS_FILE_URL=.endpoints.json

README.md

Lines changed: 70 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,67 @@ supported.
99

1010
## Dev setup
1111

12+
### Create the cluster issuer
13+
14+
To allow the jolokia api server to trust the broker in case the broker is using
15+
a TLS secured connection, you'll need to have a trust bundle to load. The trust
16+
bundle will come from a cluster issuer that is also used to issue certs for the
17+
broker.
18+
19+
One way to obtain this cluster issuer correctly configured is to deploy the
20+
upstream's jolokia api server to your cluster regardless to the fact that you
21+
may also run it locally alongside the bridge when developing locally.
22+
23+
To do that follow the section about deploying.
24+
25+
#### using the cluster issuer to secure the connection
26+
27+
The cluster issuer needs to be used to generate the cert the broker would use
28+
for its console.
29+
30+
An example for a broker called ex-aao within the myproject namespace would
31+
be:
32+
33+
> [!NOTE]
34+
> you need to adapt the domain name in the CR with the one of your cluster. One
35+
> way to obtain it is to this one liner:
36+
> `oc get -n openshift-ingress-operator ingresscontroller/default -o json | jq '.status.domain'`
37+
38+
```yaml
39+
apiVersion: cert-manager.io/v1
40+
kind: Certificate
41+
metadata:
42+
name: ex-aao-console-certificate-cert
43+
namespace: myproject
44+
spec:
45+
secretName: ex-aao-console-certificate-cert-secret
46+
privateKey:
47+
algorithm: RSA
48+
encoding: PKCS1
49+
size: 2048
50+
51+
isCA: false
52+
53+
commonName: ex-aao-console-cert
54+
55+
dnsNames:
56+
- ex-aao-wconsj-0-svc-rte-default.mydomain.tld
57+
- ex-aao-wconsj-0-svc.default
58+
issuerRef:
59+
name: jolokia-api-server-selfsigned-issuer
60+
kind: ClusterIssuer
61+
group: cert-manager.io
1262
```
63+
64+
### Build and start
65+
66+
If you have followed the previous step, you need to download the trust bundle so
67+
that your dev env has access to it and can connect to a TLS broker.
68+
69+
```sh
70+
cd trust
71+
./download-ca.sh -c jolokia-api-server-selfsigned-issuer
72+
cd ..
1373
yarn build
1474
yarn start
1575
```
@@ -19,7 +79,7 @@ yarn start
1979
After updating the `openapi.yml` file, please make sure to generate the
2080
documentation:
2181

22-
```
82+
```sh
2383
yarn run build-api-doc
2484
```
2585

@@ -51,15 +111,6 @@ deployed. for example:
51111

52112
The optional -ns (or --nosec) argument can be used to disable security.
53113

54-
---
55-
56-
**Note:**
57-
58-
you should enable security in your application. Disable security can only
59-
be used for test purposes.
60-
61-
---
62-
63114
The `deploy.sh` script uses `oc kustomize` (built-in
64115
[kustomize](https://github.com/kubernetes-sigs/kustomize)) command to configure
65116
and deploy the plugin using resources and patches defined under ./deploy
@@ -71,60 +122,21 @@ To undeploy, run
71122
./undeploy.sh
72123
```
73124

74-
### Notes about the JWT secret
75-
76-
The api server uses SECRET_ACCESS_TOKEN env var to get the secret for generating
77-
jwt tokens. It has a default value in .env for dev purposes.
78-
79-
In production you should override it with your own secret.
80-
81-
The jwt-key-gen.sh is a tool to generate a random key and used in Dockerfile.
82-
It makes sure when you build the api server image a new random key is used.
83-
84-
## Security Model of the API Server
85-
86-
The API Server provides a security model that provides authentication and authorization of incoming clients.
87-
The security can be enabled/disabled (i.e. via `API_SERVER_SECURITY_ENABLED` env var)
88-
89-
### Authentication
90-
91-
Currently the api server support `jwt` token authentication.
92-
93-
#### The login api
94-
95-
The login api is defined in openapi.yml
96-
97-
```yaml
98-
/server/login
99-
```
100-
101-
A client logs in to an api server by sending a POST request to the login path. The request body contains login information (i.e. username and password for jwt authentication type)
102-
103-
Please refer to [api.md](api.md) for details of the log api.
104-
105-
Currently the security manager uses local file to store user's info. The default users file name is `.users.json`
106-
The users file name can be configured using `USERS_FILE_URL` env var. See `.test.users.json` for sample values.
107-
108-
### Authorization
109-
110-
Currently the api server doesn't perform authorization on logged in users.
111-
112-
### Endpoints Management
113-
114-
The server keeps a list of jolokia endpoints for clients to access. The endpoints are loaded from a local file named
115-
`.endpoints.json`. Each top level entry represents a jolokia endpoint. An entry has a unique name and details to access the jolokia api. See `.test.endpoints.json` for sample values.
116-
117125
### Accessing a jolokia endpoint
118126

119-
When an authenticated client sends a request to the api-server, it should present its token in the request header
127+
When an authenticated client sends a request to the api-server, it should
128+
present its token in the request header.
120129

121-
'Authorization: Bearer `token`'
130+
'Authorization: Bearer `token`'
122131

123-
It also need to give the `targetEndpoint` in the query part of the request if the request is to access an jolokia endpoint.
132+
It also need to give the `targetEndpoint` in the query part of the request if
133+
the request is to access an jolokia endpoint.
124134

125135
For example `/execBrokerOperation?targetEndpoint=broker1`.
126136

127137
### Direct Proxy
128138

129-
Direct Proxy means a client can pass a broker's endpoint info to the api-server in order to access it via the api-server.
130-
For example the [self-provisioning plugin](https://github.com/artemiscloud/activemq-artemis-self-provisioning-plugin) uses this api to access the jolokia of a broker's jolokia endpoint.
139+
Direct Proxy means a client can pass a broker's endpoint info to the api-server
140+
in order to access it via the api-server. For example the [self-provisioning
141+
plugin](https://github.com/arkmq-org/activemq-artemis-self-provisioning-plugin)
142+
uses this api to access the jolokia of a broker's jolokia endpoint.

deploy.sh

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,37 @@ while [[ $# -gt 0 ]]; do
3535
esac
3636
done
3737

38+
# find the cert-manager operator namespace, if this can't be retrived there's no
39+
# possibility to proceed
40+
certManagerNamespace=$(oc get Subscriptions --all-namespaces -ojson | jq -r '.items[] | select(.spec.name == "cert-manager") | .metadata.namespace')
41+
if test -z "$certManagerNamespace"
42+
then
43+
echo "cert-manager's namespace can't be determined, check that it is installed"
44+
oc get Subscriptions --all-namespaces
45+
exit 1
46+
fi
47+
echo "cert-manager's namespace: $certManagerNamespace"
48+
49+
# retrieve the cluster domain to produce a valid cluster issuer
50+
clusterDomain=$(oc get -n openshift-ingress-operator ingresscontroller/default -o json | jq -r '.status.domain')
51+
if test -z "$certManagerNamespace"
52+
then
53+
echo "The cluster domain can't be retrived"
54+
exit 1
55+
fi
56+
echo "cluster domain: $clusterDomain"
57+
3858
echo "deploying using image: ${API_SERVER_IMAGE}"
39-
oc kustomize deploy | sed "s|image: .*|image: ${API_SERVER_IMAGE}|" | oc apply -f -
59+
oc kustomize deploy \
60+
| sed "s|image: .*|image: ${API_SERVER_IMAGE}|" \
61+
| sed "s|- issuer.mydomain.tld|- issuer.${clusterDomain}|" \
62+
| oc apply -f -
63+
64+
65+
while ! kubectl get secret jolokia-api-server-selfsigned-ca-cert-secret --namespace openshift-operators; do echo "Waiting for the CA"; sleep 1; done
66+
# copy the secret from the cert-manager namespace to the jolokia api server
67+
# namespace
68+
oc get secret jolokia-api-server-selfsigned-ca-cert-secret \
69+
--namespace=openshift-operators -oyaml \
70+
| sed s/"namespace: ${certManagerNamespace}"/"namespace: activemq-artemis-jolokia-api-server"/\ \
71+
| kubectl apply -n activemq-artemis-jolokia-api-server -f -

deploy/cluster-issuer.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: ClusterIssuer
3+
metadata:
4+
name: jolokia-api-server-selfsigned-root-issuer
5+
spec:
6+
selfSigned: {}
7+
---
8+
apiVersion: cert-manager.io/v1
9+
kind: Certificate
10+
metadata:
11+
name: jolokia-api-server-selfsigned-ca-cert
12+
namespace: openshift-operators
13+
spec:
14+
isCA: true
15+
commonName: jolokia-api-server-selfsigned-ca-cert
16+
secretName: jolokia-api-server-selfsigned-ca-cert-secret
17+
privateKey:
18+
algorithm: ECDSA
19+
size: 256
20+
dnsNames:
21+
- issuer.mydomain.tld
22+
issuerRef:
23+
name: jolokia-api-server-selfsigned-root-issuer
24+
kind: ClusterIssuer
25+
group: cert-manager.io
26+
---
27+
apiVersion: cert-manager.io/v1
28+
kind: ClusterIssuer
29+
metadata:
30+
name: jolokia-api-server-selfsigned-issuer
31+
spec:
32+
ca:
33+
secretName: jolokia-api-server-selfsigned-ca-cert-secret

deploy/deployment.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ spec:
1818
containers:
1919
- name: activemq-artemis-jolokia-api-server
2020
image: quay.io/arkmq-org/activemq-artemis-jolokia-api-server:latest
21+
env:
22+
- name: NODE_EXTRA_CA_CERTS
23+
value: '/var/jolokia-api-server-selfsigned-ca-cert-secret/ca.crt'
2124
ports:
2225
- containerPort: 9443
2326
protocol: TCP
@@ -38,11 +41,18 @@ spec:
3841
- name: plugin-serving-cert
3942
readOnly: true
4043
mountPath: /var/serving-cert
44+
- name: jolokia-api-server-selfsigned-ca-cert-secret
45+
readOnly: true
46+
mountPath: /var/jolokia-api-server-selfsigned-ca-cert-secret
4147
volumes:
4248
- name: plugin-serving-cert
4349
secret:
4450
secretName: plugin-serving-cert
4551
defaultMode: 420
52+
- name: jolokia-api-server-selfsigned-ca-cert-secret
53+
secret:
54+
secretName: jolokia-api-server-selfsigned-ca-cert-secret
55+
defaultMode: 420
4656
restartPolicy: Always
4757
dnsPolicy: ClusterFirst
4858
strategy:

deploy/kustomization.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
namespace: activemq-artemis-jolokia-api-server
2-
31
resources:
42
- namespace.yaml
3+
- cluster-issuer.yaml
54
- deployment.yaml
65
- service.yaml

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"format:all": "prettier --config ./.prettierrc.yml --write './src/**/*'",
1919
"lint": "yarn eslint src --fix && stylelint \"src/**/*.css\" --allow-empty-input --fix",
2020
"prepare": "husky install",
21-
"start": "node ./dist/app.js",
21+
"start": "NODE_EXTRA_CA_CERTS=./trust/ca.crt node ./dist/app.js",
2222
"test": "NODE_TLS_REJECT_UNAUTHORIZED=0 TZ=UTC jest --runInBand",
2323
"test:coverage": "yarn run test --watch=false --coverage",
2424
"test:generate-output": "yarn test -- --json --outputFile=.jest-test-results.json",

src/api/apiutil/artemis_jolokia.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { logger } from '../../utils/logger';
22
import { AuthOptions } from '../../utils/security_util';
33
import fetch from 'node-fetch';
4-
import https from 'https';
54

65
// search the broker
76
const brokerSearchPattern = 'org.apache.activemq.artemis:broker=*';
@@ -122,12 +121,6 @@ export class ArtemisJolokia {
122121
headers: headers,
123122
};
124123

125-
if (reqUrl.startsWith('https')) {
126-
authOpts['agent'] = new https.Agent({
127-
rejectUnauthorized: false,
128-
});
129-
}
130-
131124
authOpts.headers.set('Authorization', 'Bearer ' + token);
132125
return authOpts;
133126
}
@@ -169,6 +162,10 @@ export class ArtemisJolokia {
169162
.then((message) => {
170163
const resp: JolokiaResponseType = JSON.parse(message);
171164
return resp.value;
165+
})
166+
.catch((err) => {
167+
logger.error(err);
168+
throw err;
172169
});
173170

174171
return reply;
@@ -211,6 +208,7 @@ export class ArtemisJolokia {
211208
return resp.value;
212209
})
213210
.catch((err) => {
211+
logger.error(err);
214212
throw err;
215213
});
216214

@@ -251,6 +249,7 @@ export class ArtemisJolokia {
251249
return jsonObj as JolokiaExecResponse;
252250
})
253251
.catch((err) => {
252+
logger.error(err);
254253
throw err;
255254
});
256255

@@ -287,6 +286,7 @@ export class ArtemisJolokia {
287286
return resp;
288287
})
289288
.catch((err) => {
289+
logger.error(err);
290290
throw err;
291291
});
292292
return reply;

trust/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ca.crt

0 commit comments

Comments
 (0)