Skip to content

Commit 346e225

Browse files
authored
cloudsso - make api resource access call cloudsso and fallback to zms (#3051)
1 parent 57317dd commit 346e225

File tree

5 files changed

+193
-35
lines changed

5 files changed

+193
-35
lines changed

ui/src/__tests__/server/clients.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ describe('clients test', () => {
3737
msd: 'test',
3838
ums: 'test',
3939
zts: 'test',
40+
cloud_sso: 'test',
4041
};
4142

4243
clients.load(config, {}).catch((err) => {

ui/src/__tests__/server/handlers/api.test.js

Lines changed: 120 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const config = {
3939
userDomain: 'test-user-domain',
4040
serviceHeaderLinks: [],
4141
templates: ['openhouse'],
42+
callCloudSSO: true,
4243
};
4344
const SEVEN_SECONDS_TIMEOUT = 1000 * 7;
4445
const secrets = {};
@@ -56,6 +57,22 @@ describe('Fetchr Server API Test', () => {
5657
sinon.stub(CLIENTS, 'load').returns(Promise.resolve());
5758
sinon.stub(CLIENTS, 'middleware').returns((req, res, next) => {
5859
req.clients = {
60+
cloud_sso: {
61+
getResourceAccessList: (params, callback) =>
62+
params.action === 'forcefailcloudsso' ||
63+
params.action === 'forcefailboth'
64+
? callback({ status: 503 }, null)
65+
: callback(undefined, {
66+
resources: {
67+
principal: 'user.dummy1',
68+
assertions: [
69+
{
70+
dummyProperty: 'dummyValue',
71+
},
72+
],
73+
},
74+
}),
75+
},
5976
zms: {
6077
putAssertion: (params, callback) =>
6178
params.forcefail
@@ -312,14 +329,20 @@ describe('Fetchr Server API Test', () => {
312329
],
313330
}),
314331
getResourceAccessList: (params, callback) =>
315-
params.forcefail
316-
? callback({ status: 404 }, null)
332+
params.action === 'forcefailboth'
333+
? callback(
334+
{
335+
status: 503,
336+
message: { message: 'zms fail' },
337+
},
338+
null
339+
)
317340
: callback(undefined, {
318341
resources: {
319-
principal: 'user.dummy1',
342+
principal: 'user.dummy2',
320343
assertions: [
321344
{
322-
dummyProperty: 'dummyValue',
345+
dummyProperty: 'dummyValue2',
323346
},
324347
],
325348
},
@@ -362,6 +385,8 @@ describe('Fetchr Server API Test', () => {
362385
};
363386
next();
364387
});
388+
});
389+
beforeEach(async () => {
365390
api.load(config, secrets).then(() => {
366391
expressApp.use(bodyParser.urlencoded({ extended: false }));
367392
expressApp.use(bodyParser.json());
@@ -1161,6 +1186,52 @@ describe('Fetchr Server API Test', () => {
11611186
]);
11621187
});
11631188
});
1189+
it('getResourceAccessList test cloudsso success', async () => {
1190+
await request(expressApp)
1191+
.get('/api/v1/resource-access')
1192+
.then((res) => {
1193+
expect(res.body).toEqual({
1194+
resources: {
1195+
principal: 'user.dummy1',
1196+
assertions: [
1197+
{
1198+
dummyProperty: 'dummyValue',
1199+
},
1200+
],
1201+
},
1202+
});
1203+
});
1204+
});
1205+
1206+
it('getResourceAccessList test callCloudSSO is false, zms call success', async () => {
1207+
api.load({ ...config, callCloudSSO: false }, secrets).then(() => {
1208+
expressApp.use(bodyParser.urlencoded({ extended: false }));
1209+
expressApp.use(bodyParser.json());
1210+
expressApp.use((req, res, next) => {
1211+
req.session = {
1212+
shortId: 'testuser',
1213+
};
1214+
req.csrfToken = () => '1234';
1215+
next();
1216+
});
1217+
api.route(expressApp);
1218+
});
1219+
1220+
await request(expressApp)
1221+
.get('/api/v1/resource-access')
1222+
.then((res) => {
1223+
expect(res.body).toEqual({
1224+
resources: {
1225+
principal: 'user.dummy2',
1226+
assertions: [
1227+
{
1228+
dummyProperty: 'dummyValue2',
1229+
},
1230+
],
1231+
},
1232+
});
1233+
});
1234+
});
11641235
});
11651236
describe('failure tests', () => {
11661237
it('putAssertion test failure', async () => {
@@ -1317,22 +1388,59 @@ describe('Fetchr Server API Test', () => {
13171388
expect(res.status).toEqual(404);
13181389
});
13191390
});
1320-
it('getResourceAccessList test success', async () => {
1391+
1392+
it('getResourceAccessList test cloudsso fail zms success', async () => {
13211393
await request(expressApp)
1322-
.get('/api/v1/resource-access')
1394+
.post('/api/v1')
1395+
.send({
1396+
requests: {
1397+
g0: {
1398+
resource: 'resource-access',
1399+
operation: 'read',
1400+
params: {
1401+
action: 'forcefailcloudsso',
1402+
},
1403+
},
1404+
},
1405+
})
13231406
.then((res) => {
13241407
expect(res.body).toEqual({
1325-
resources: {
1326-
principal: 'user.dummy1',
1327-
assertions: [
1328-
{
1329-
dummyProperty: 'dummyValue',
1408+
g0: {
1409+
data: {
1410+
resources: {
1411+
principal: 'user.dummy2',
1412+
assertions: [
1413+
{
1414+
dummyProperty: 'dummyValue2',
1415+
},
1416+
],
13301417
},
1331-
],
1418+
},
1419+
meta: {},
13321420
},
13331421
});
13341422
});
13351423
});
1424+
it('getResourceAccessList test both cloudsso and zms fail', async () => {
1425+
await request(expressApp)
1426+
.post('/api/v1/resource-access')
1427+
.send({
1428+
requests: {
1429+
g0: {
1430+
resource: 'resource-access',
1431+
operation: 'read',
1432+
params: {
1433+
action: 'forcefailboth',
1434+
},
1435+
},
1436+
},
1437+
})
1438+
.then((res) => {
1439+
expect(res.body).toEqual({
1440+
message: 'zms fail',
1441+
});
1442+
});
1443+
});
13361444
it('getRolesForReview test success', async () => {
13371445
await request(expressApp)
13381446
.get('/api/v1/roles-review')

ui/src/config/default-config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ const config = {
4343
msd: process.env.MSD_LOGIN_URL || 'https://localhost:4443/msd/v1/',
4444
zts: process.env.ZTS_LOGIN_URL || 'https://localhost:4443/zts/v1/',
4545
ums: process.env.UMS_LOGIN_URL || 'https://localhost:4443/ums/v1/',
46+
cloud_sso:
47+
process.env.ZMS_SERVER_URL || 'https://localhost:4443/zms/v1/',
4648
authHeader: 'Athenz-Principal-Auth',
4749
strictSSL: false,
4850
user: 'ui-server',
@@ -177,6 +179,7 @@ const config = {
177179
numberOfRetry: 2,
178180
serverCipherSuites:
179181
'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
182+
callCloudSSO: true,
180183
},
181184
unittest: {
182185
testdata: { ...testdata },
@@ -227,6 +230,7 @@ const config = {
227230
numberOfRetry: 2,
228231
serverCipherSuites:
229232
'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
233+
callCloudSSO: true,
230234
},
231235
};
232236

ui/src/server/clients.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ function refreshCertClients(config, options) {
5656
},
5757
});
5858

59+
// cloud_sso is a cache of zms's resource access lists
60+
CLIENTS.cloud_sso = rdlRest({
61+
apiHost: config.cloud_sso,
62+
rdl: require('../config/zms.json'),
63+
requestOpts: {
64+
strictSSL: config.strictSSL,
65+
},
66+
});
67+
5968
userService.refreshUserData(config);
6069

6170
return Promise.resolve();
@@ -95,6 +104,7 @@ module.exports.middleware = function middleware() {
95104
msd: CLIENTS.msd(req, setCookieinClients(req)),
96105
zts: CLIENTS.zts(req, setCookieinClients(req)),
97106
ums: CLIENTS.ums(req, setCookieinClients(req)),
107+
cloud_sso: CLIENTS.cloud_sso(req, setOktaCookieinClients(req)),
98108
};
99109
next();
100110
};

ui/src/server/handlers/api.js

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3226,34 +3226,68 @@ Fetchr.registerService({
32263226
Fetchr.registerService({
32273227
name: 'resource-access',
32283228
read(req, resource, params, config, callback) {
3229-
req.clients.zms.getResourceAccessList(
3230-
{
3231-
action: params.action,
3232-
principal: `${appConfig.userDomain}.${req.session.shortId}`,
3233-
},
3234-
(err, list) => {
3235-
if (err) {
3236-
if (err.status === 404) {
3237-
callback(null, []);
3229+
let cloudSSOCallFailed = false;
3230+
if (appConfig.callCloudSSO) {
3231+
req.clients.cloud_sso.getResourceAccessList(
3232+
{
3233+
action: params.action,
3234+
principal: `${appConfig.userDomain}.${req.session.shortId}`,
3235+
},
3236+
(err, list) => {
3237+
if (err) {
3238+
if (err.status === 404) {
3239+
callback(null, []);
3240+
} else {
3241+
debug(
3242+
`principal: ${req.session.shortId} rid: ${
3243+
req.headers.rid
3244+
} Error from Cloud SSO while calling getResourceAccessList API: ${JSON.stringify(
3245+
errorHandler.fetcherError(err)
3246+
)}`
3247+
);
3248+
// Fallback to ZMS if Cloud SSO call fails
3249+
cloudSSOCallFailed = true;
3250+
}
32383251
} else {
3239-
debug(
3240-
`principal: ${req.session.shortId} rid: ${
3241-
req.headers.rid
3242-
} Error from ZMS while calling getResourceAccessList API: ${JSON.stringify(
3243-
errorHandler.fetcherError(err)
3244-
)}`
3245-
);
3246-
callback(errorHandler.fetcherError(err));
3252+
if (!list || !list.resources) {
3253+
callback(null, []);
3254+
} else {
3255+
callback(null, list);
3256+
}
32473257
}
3248-
} else {
3249-
if (!list || !list.resources) {
3250-
callback(null, []);
3258+
}
3259+
);
3260+
}
3261+
if (!appConfig.callCloudSSO || cloudSSOCallFailed) {
3262+
req.clients.zms.getResourceAccessList(
3263+
{
3264+
action: params.action,
3265+
principal: `${appConfig.userDomain}.${req.session.shortId}`,
3266+
},
3267+
(err, list) => {
3268+
if (err) {
3269+
if (err.status === 404) {
3270+
callback(null, []);
3271+
} else {
3272+
debug(
3273+
`principal: ${req.session.shortId} rid: ${
3274+
req.headers.rid
3275+
} Error from ZMS while calling getResourceAccessList API: ${JSON.stringify(
3276+
errorHandler.fetcherError(err)
3277+
)}`
3278+
);
3279+
callback(errorHandler.fetcherError(err));
3280+
}
32513281
} else {
3252-
callback(null, list);
3282+
if (!list || !list.resources) {
3283+
callback(null, []);
3284+
} else {
3285+
callback(null, list);
3286+
}
32533287
}
32543288
}
3255-
}
3256-
);
3289+
);
3290+
}
32573291
},
32583292
});
32593293

@@ -3346,6 +3380,7 @@ module.exports.load = function (config, secrets) {
33463380
serviceHeaderLinks: config.serviceHeaderLinks,
33473381
templates: config.templates,
33483382
numberOfRetry: config.numberOfRetry,
3383+
callCloudSSO: config.callCloudSSO,
33493384
};
33503385
return CLIENTS.load(config, secrets);
33513386
};

0 commit comments

Comments
 (0)