Skip to content

Commit 7071826

Browse files
lavocattMsarawan
authored andcommitted
[#44] broker creation: enabling rbac
This commit enables a RBAC control for the broker. When the user decides to lock down the acccess to the broker using tokens, it has for side effect to make the broker require a login to communicate with acceptors. In this commit we make sure that the user is able to create and configure users so that the acceptors are always accessible.
1 parent 33e1eaa commit 7071826

File tree

8 files changed

+697
-61
lines changed

8 files changed

+697
-61
lines changed

locales/en/plugin__activemq-artemis-self-provisioning-plugin.json

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,12 @@
9393
"Memory Usage Metrics": "Memory Usage Metrics",
9494
"CPU Usage Metrics": "CPU Usage Metrics",
9595
"Metrics": "Metrics",
96+
"Error loading secrets": "Error loading secrets",
9697
"Test the connection to": "Test the connection to",
97-
"Download the secret:": "Download the secret:",
98-
"Run the command with the secret": "Run the command with the secret",
98+
"Download the cert:": "Download the cert:",
99+
"Your setup requires having a username and password for connecting to the acceptor": "Your setup requires having a username and password for connecting to the acceptor",
100+
"find one in the extra-users.properties entry of the jaas-config": "find one in the extra-users.properties entry of the jaas-config",
101+
"Run the command below (it assumes that the cert is stored in /tmp)": "Run the command below (it assumes that the cert is stored in /tmp)",
99102
"Copy to clipboard": "Copy to clipboard",
100103
"Successfully copied to clipboard!": "Successfully copied to clipboard!",
101104
"Connectivity": "Connectivity",
@@ -178,10 +181,12 @@
178181
"No {{name}} configured": "No {{name}} configured",
179182
"There is no {{name}} in your configuration, to add one click on the button below.": "There is no {{name}} in your configuration, to add one click on the button below.",
180183
"Add": "Add",
181-
"Enable RBAC": "Enable RBAC",
182-
"enable RBAC": "enable RBAC",
183-
"disable RBAC": "disable RBAC",
184+
"RBAC enabled": "RBAC enabled",
185+
"RBAC disabled": "RBAC disabled",
184186
"Configuration for the token authentication": "Configuration for the token authentication",
187+
"Security roles": "Security roles",
188+
"Configure which user can access which resources on the broker": "Configure which user can access which resources on the broker",
189+
"Add a security role": "Add a security role",
185190
"Service account": "Service account",
186191
"Select a service account that has the permission to perform a token review": "Select a service account that has the permission to perform a token review",
187192
"The selected service account must within the same namespace as the broker you want to deploy and must have a cluster wide role binding to the `system:auth-delegator` role.": "The selected service account must within the same namespace as the broker you want to deploy and must have a cluster wide role binding to the `system:auth-delegator` role.",
@@ -196,7 +201,21 @@
196201
"This custom jaas config will allow the user specified as administrator to access the jolokia endpoint of the broker.": "This custom jaas config will allow the user specified as administrator to access the jolokia endpoint of the broker.",
197202
"Create the jaas config": "Create the jaas config",
198203
"Select a jaas config": "Select a jaas config",
204+
"If during your editing of the jaas-config you changed the roles, you can rebuild the security roles in order to take into account your changes": "If during your editing of the jaas-config you changed the roles, you can rebuild the security roles in order to take into account your changes",
205+
"edit": "edit",
206+
"Rebuilding the security roles will override the ones that are already configured.": "Rebuilding the security roles will override the ones that are already configured.",
207+
"rebuild security roles": "rebuild security roles",
199208
"Create a new jaas config": "Create a new jaas config",
209+
"Show the jaas-config's roles and users": "Show the jaas-config's roles and users",
210+
"Openshift users allowed to read the jolokia endpoint": "Openshift users allowed to read the jolokia endpoint",
211+
"Group": "Group",
212+
"OpenShift usernames (comma separated)": "OpenShift usernames (comma separated)",
213+
"Users allowed to access the broker": "Users allowed to access the broker",
214+
"Username": "Username",
215+
"Password": "Password",
216+
"Roles used for security rules": "Roles used for security rules",
217+
"Role": "Role",
218+
"Users (comma separated)": "Users (comma separated)",
200219
"Version:": "Version:",
201220
"Self Signed:": "Self Signed:",
202221
"SerialNumber:": "SerialNumber:",

src/brokers/broker-details/components/Overview/Overview.container.tsx

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
useLabelsModal,
55
} from '@openshift-console/dynamic-plugin-sdk';
66
import {
7+
Alert,
8+
AlertVariant,
79
Bullseye,
810
Button,
911
Card,
@@ -66,7 +68,7 @@ const useGetIssuerCa = (
6668

6769
const useGetTlsSecret = (cr: BrokerCR, acceptor: Acceptor) => {
6870
const [secretName, hasSecretName] = useGetIssuerCa(cr, acceptor);
69-
const [secrets] = useK8sWatchResource<SecretResource[]>({
71+
const [secrets, loaded, loadError] = useK8sWatchResource<SecretResource[]>({
7072
groupVersionKind: {
7173
version: 'v1',
7274
kind: 'Secret',
@@ -76,23 +78,23 @@ const useGetTlsSecret = (cr: BrokerCR, acceptor: Acceptor) => {
7678
namespace: cr.metadata.namespace,
7779
});
7880

81+
const secret = secrets.find((secret) => secret.metadata?.name === secretName);
82+
7983
if ((hasSecretName && !secretName) || !secrets) {
80-
return undefined;
84+
return [undefined, loaded, loadError];
8185
}
8286

83-
const secret = secrets.find((secret) => secret.metadata?.name === secretName);
84-
85-
if (!(secret && secret && secret.data && secret.data['tls.crt'])) {
86-
return undefined;
87+
if (!(secret && secret.data && secret.data['tls.crt'])) {
88+
return [undefined, loaded, loadError];
8789
}
88-
return secret;
90+
return [secret, loaded, loadError];
8991
};
9092

91-
type SecretDownloaLinkProps = {
93+
type SecretDownloadLinkProps = {
9294
secret: SecretResource;
9395
};
9496

95-
const SecretDownloadLink: FC<SecretDownloaLinkProps> = ({ secret }) => {
97+
const SecretDownloadLink: FC<SecretDownloadLinkProps> = ({ secret }) => {
9698
return (
9799
<a
98100
href={
@@ -120,9 +122,10 @@ const HelpConnectAcceptor: FC<HelperConnectAcceptorProps> = ({
120122
acceptor,
121123
}) => {
122124
const { t } = useTranslation();
123-
const secret = useGetTlsSecret(cr, acceptor);
125+
const [secret, loaded, loadError] = useGetTlsSecret(cr, acceptor);
124126
const ingressHost = getIssuerIngressHostForAcceptor(cr, acceptor, 0);
125127
const [copied, setCopied] = useState(false);
128+
const isSecuredByToken = cr.spec.adminUser === undefined;
126129

127130
const clipboardCopyFunc = (text: string) => {
128131
navigator.clipboard.writeText(text.toString());
@@ -132,13 +135,20 @@ const HelpConnectAcceptor: FC<HelperConnectAcceptorProps> = ({
132135
clipboardCopyFunc(text);
133136
setCopied(true);
134137
};
135-
if (!secret) {
138+
if (!loaded || !secret) {
136139
return (
137140
<Bullseye>
138141
<Spinner size="lg" />
139142
</Bullseye>
140143
);
141144
}
145+
if (loadError) {
146+
return (
147+
<Alert variant={AlertVariant.danger} title={t('Error loading secrets')}>
148+
{loadError}
149+
</Alert>
150+
);
151+
}
142152

143153
const code =
144154
"./artemis check queue --name TEST --produce 10 --browse 10 --consume 10 --url 'tcp://" +
@@ -154,10 +164,34 @@ const HelpConnectAcceptor: FC<HelperConnectAcceptorProps> = ({
154164
<DescriptionListDescription>
155165
<List>
156166
<ListItem>
157-
{t('Download the secret:')} <SecretDownloadLink secret={secret} />
167+
{t('Download the cert:')} <SecretDownloadLink secret={secret} />
158168
</ListItem>
169+
{isSecuredByToken && (
170+
<ListItem>
171+
{t(
172+
'Your setup requires having a username and password for connecting to the acceptor',
173+
)}
174+
<Button
175+
variant="link"
176+
onClick={() =>
177+
window.open(
178+
'ns/' +
179+
cr.metadata.namespace +
180+
'/secrets/' +
181+
cr.spec.deploymentPlan.extraMounts.secrets[0],
182+
)
183+
}
184+
>
185+
{t(
186+
'find one in the extra-users.properties entry of the jaas-config',
187+
)}
188+
</Button>
189+
</ListItem>
190+
)}
159191
<ListItem>
160-
{t('Run the command with the secret')} (here in /tmp)
192+
{t(
193+
'Run the command below (it assumes that the cert is stored in /tmp)',
194+
)}
161195
<CodeBlock
162196
actions={
163197
<CodeBlockAction>

src/k8s/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,14 @@ export type ResourceTemplate = {
7979
};
8080
};
8181

82+
export type Env = {
83+
name: string;
84+
value: string;
85+
};
86+
8287
export type BrokerCR = K8sResourceCommon & {
8388
spec?: {
89+
env?: Env[];
8490
ingressDomain?: string;
8591
connectors?: Connector[];
8692
acceptors?: Acceptor[];
@@ -143,7 +149,9 @@ export type ConfigMapSecretResource = K8sResourceCommon & {
143149
kind: 'Secret';
144150
data?: {
145151
'login.config'?: string;
146-
'k8s-roles.properties'?: string;
152+
'k8s-users-to-roles-mapping.properties'?: string;
153+
'extra-roles.properties'?: string;
154+
'extra-users.properties'?: string;
147155
};
148156
};
149157

src/reducers/7.13/reducer.test.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,68 @@ describe('test the creation broker reducer', () => {
1313
payload: true,
1414
});
1515
expect(newState.cr.spec.adminUser).toBe(undefined);
16+
expect(newState.cr.spec.env[0].name).toBe('JAVA_ARGS_APPEND');
17+
expect(newState.cr.spec.env[0].value).toBe('-Dhawtio.realm=token');
1618
const newState2 = reducer713(newState, {
1719
operation: ArtemisReducerOperations713.isUsingToken,
1820
payload: false,
1921
});
2022
expect(newState2.cr.spec.adminUser).toBe('admin');
2123
expect(newState2.cr.spec.deploymentPlan.extraMounts).toBe(undefined);
2224
expect(newState2.cr.spec.deploymentPlan.podSecurity).toBe(undefined);
25+
expect(newState2.cr.spec.env).toBe(undefined);
2326
});
24-
it('test setting jaas config', () => {
27+
28+
it('test enabling token over an existing env', () => {
2529
const initialState = newArtemisCR('namespace');
30+
initialState.cr.spec.env = [
31+
{ name: 'JAVA_ARGS_APPEND', value: '-Dtest=true' },
32+
{ name: 'OTHERPROP', value: 'TEST' },
33+
];
2634
const newState = reducer713(initialState, {
35+
operation: ArtemisReducerOperations713.isUsingToken,
36+
payload: true,
37+
});
38+
expect(newState.cr.spec.adminUser).toBe(undefined);
39+
expect(newState.cr.spec.env[0].name).toBe('JAVA_ARGS_APPEND');
40+
expect(newState.cr.spec.env[0].value).toBe(
41+
'-Dtest=true -Dhawtio.realm=token',
42+
);
43+
const newState2 = reducer713(newState, {
44+
operation: ArtemisReducerOperations713.isUsingToken,
45+
payload: false,
46+
});
47+
expect(newState2.cr.spec.adminUser).toBe('admin');
48+
expect(newState2.cr.spec.deploymentPlan.extraMounts).toBe(undefined);
49+
expect(newState2.cr.spec.deploymentPlan.podSecurity).toBe(undefined);
50+
expect(newState.cr.spec.env[0].name).toBe('JAVA_ARGS_APPEND');
51+
expect(newState.cr.spec.env[0].value).toBe('-Dtest=true');
52+
expect(newState.cr.spec.env[1].name).toBe('OTHERPROP');
53+
expect(newState.cr.spec.env[1].value).toBe('TEST');
54+
});
55+
56+
it('test setting jaas config', () => {
57+
const initialState = newArtemisCR('namespace');
58+
const newState0 = reducer713(initialState, {
59+
operation: ArtemisReducerOperations713.setSecurityRoles,
60+
payload: new Map([['securityRoles.test', 'true']]),
61+
});
62+
const newState = reducer713(newState0, {
2763
operation: ArtemisReducerOperations713.setJaasExtraConfig,
2864
payload: 'something',
2965
});
3066
expect(newState.cr.spec.deploymentPlan.extraMounts.secrets[0]).toBe(
3167
'something',
3268
);
69+
expect(newState.cr.spec.brokerProperties.length).toBe(0);
3370
const newState2 = reducer713(newState, {
3471
operation: ArtemisReducerOperations713.setJaasExtraConfig,
3572
payload: undefined,
3673
});
3774
expect(newState2.cr.spec.deploymentPlan.extraMounts).toBe(undefined);
75+
expect(newState.cr.spec.brokerProperties.length).toBe(0);
3876
});
77+
3978
it('test setting service account', () => {
4079
const initialState = newArtemisCR('namespace');
4180
const newState = reducer713(initialState, {
@@ -51,14 +90,24 @@ describe('test the creation broker reducer', () => {
5190
});
5291
expect(newState2.cr.spec.deploymentPlan.podSecurity).toBe(undefined);
5392
});
93+
5494
it('test resetting to 7.12 after setting 7.13 settings', () => {
5595
const initialState = newArtemisCR('namespace');
5696
const newState = reducer713(initialState, {
5797
operation: ArtemisReducerOperations713.isUsingToken,
5898
payload: true,
5999
});
100+
// use the setSecurityRoles method to set a security role and also another
101+
// generic broker property
102+
const newState1 = reducer713(newState, {
103+
operation: ArtemisReducerOperations713.setSecurityRoles,
104+
payload: new Map([
105+
['something', 'else'],
106+
['securityRoles.test', 'true'],
107+
]),
108+
});
60109
expect(newState.cr.spec.adminUser).toBe(undefined);
61-
const newState2 = reducer713(newState, {
110+
const newState2 = reducer713(newState1, {
62111
operation: ArtemisReducerOperations713.setJaasExtraConfig,
63112
payload: 'something',
64113
});
@@ -82,6 +131,9 @@ describe('test the creation broker reducer', () => {
82131
});
83132
expect(newState5.cr.spec.deploymentPlan.podSecurity).toBe(undefined);
84133
expect(newState5.cr.spec.deploymentPlan.extraMounts).toBe(undefined);
134+
expect(newState5.cr.spec.env).toBe(undefined);
85135
expect(newState5.cr.spec.adminUser).toBe('admin');
136+
expect(newState5.cr.spec.brokerProperties.length).toBe(1);
137+
expect(newState5.cr.spec.brokerProperties[0]).toBe('something=else');
86138
});
87139
});

0 commit comments

Comments
 (0)