Skip to content

Commit

Permalink
Create Latest Release - sec fixes (#491)
Browse files Browse the repository at this point in the history
* First pass at new consumers table.

* Stub out filters.

* Finish base filter behavior.

* Finish basic POC of filters.

* Fix up consumers list page.

* Add proper id to search logic

* First pass at approval dialog

* First pass at laying out access request dialog.

* Add working forms.

* Fix possible empty object

* Proxy access requests.

* Add missing allowed query.

* Touch up some files.

* Wire up conditional select options.

* Wire up auth and controls.

* Bubble controls up to the top level.

* Finish forms and add data-testids

* First pass at new consumers table.

* Stub out filters.

* Finish base filter behavior.

* Finish basic POC of filters.

* Fix up consumers list page.

* Add proper id to search logic

* First pass at consumers unit tests.

* Fix type error.

* Unit tests for consumers index page functionality.

* Add mocks for access request

* Fix some tests, start grant access dialog

* Add tests for request details and controls

* Add more unit tests for access requests so consumers page tests can be lighter

* Dialog and controls tests.

* Add grant access dialog tests.

* Clean up consumers tests.

* First pass at detail page layout.

* Add restrictions.

* Handle restrictions

* UI layout tweaks and add edit form.

* First pass at editing controls.

* Finish first pass at refactor of consumers.

* Update tests.

* Finish IP restrictions test.

* Fix up tests.

* Add some coverage and fix broken tests.

* Add some edit dialog tests

* initial backend changes for getFilteredNamespaceConsumers

* add backend for getNamespaceConsumerAccess

* put back application owner in detail page

* upd backend support for getConsumerProdEnvAccess

* Update tests, organize MSW directory and add new consumers page query

* backend getConsumerProdEnvAccess query

* upd tests for backend

* upd backend ConsumerProdEnvAccess object

* Wire up auth, wire up UI for new API changes.

* upd services for consumer access detail

* Wire up edit dialog with new API.

* Fix type errors

* Fix some props access on the consumers detail page.

* Remove debugger

* upd backend updateConsumerAccess and saveConsumerLabels

* adj request details on consumer

* Update edit dialog and mock data.

* Add app owner.

* upd app owner for consumer detail and graphql whitelist

* upd whitelist for access review

* add allConsumerGroupLabels

* Add new manage labels dialog.

* tweak grant access dialog

* upd permissions and whitelist for saving labels

* Added Scenarios for Refresh Credentials, API Test and update existing client credential scenarios

* Wire up manage labels on consumers index page.

* Update grant access dialog

* add filter for consumer list

* add filter for consumer list

* add revokeAccessFromConsumer backend call

* for grant access scopes and roles are optional

* add revokeAccessFromConsumer backend call

* request details optional on edit dialog

* 1) Change config of oauth2 proxy and keycloak
2) Update cypress tests

* Refactor filters.

* filters structure for labels changed a bit

* Use names in filters instead of ids. Prevent duplicates

* wire up filtering for consumers

* wire up consumer scope and role backend for filter selection

* Wire up labels to the UI

* fix failing build

* add backend scope search logic

* Add loading state to filters.

* Add new add label group interface.

* new whitelist query for manage labels

* save labels remove blank label

* Update labels functionality, rework filters.

* add whitelist for consumer list query

* consumer read for api owner

* fix a ssr invalid query

* Cache fixes, proper naming in request dialog

* Add caching to filters, minor UI improvements.

* updates for consumer plugins

* fix edit consumer

* disable filtering

* handle services not linked to products

* inc whitelist for reject request

* fix plugin matching for consumer detail

* filter bug

* Fix the filters when no session storage.

* upd plugin service and route lisst

* add role update for consumer

* Add labels to access request

* Add test-ids

* resource tune for proto-generic-api and -mongodb

* wire up labels on access request

* remove dev,test,prod on push from ci-build-deploy

* Add revoke and hide application row if null

* fix for revoking access

* missing whitelist for revoke access

* 1)updated scenarios as per new Consumer UI
2)Added data-testid in filrwes.tsx page
3)Update keystone db schema as per new changes

* upd query types

* upd types

* remove svc accts from consumer list and fix plugin error

* stop using service access id in consumer list

* fix consumer product edit dialog

* improve plugin update comparison

* upd plugins when grant new product to consumer

* remove from whitelist the deleteGatewayConsumer

* delete consumer upds

* fix my access and access lists

* dedup list of scopes

* Add some custom error messages

* Remove bcsc user menu option

* Use unified error in toasts

* fix 427 api key not getting deleted

* resolve 443 creds for jwt key pair

* fix org dataset operations

* Standardize toasts to all be closable with only a startcase capitalized

* add test branch back in to ci-build-deploy

* fix revoke access whitelist

* Comment out flaky verification step

* fix ci-build-deploy indent

* Fix yaml formatting

* add in resources

* run as production when starting keystone

* fix allProductsByNamespace showing too much

* fix unable to load form for access request

* fix gateway services showing too many services

* Added Test to verify directory details for the namespace that has no directory

* Added test to verify namespace having no directory

* improve log security

* fix wrong role for identity provider

* fix ds api error response dataset

* fix business profile not displaying

* remove old pages for requests

* Update expected status code when call the API with non exist directory ID

Co-authored-by: Joshua Jones <[email protected]>
Co-authored-by: ikethecoder <[email protected]>
Co-authored-by: Niraj Patel <[email protected]>
Co-authored-by: nirajCITZ <[email protected]>
Co-authored-by: Justin Tendeck <[email protected]>
Co-authored-by: ikethecoder <[email protected]>
Co-authored-by: jTendeck <[email protected]>
  • Loading branch information
8 people authored Aug 17, 2022
1 parent f1aae30 commit 3ae1d2b
Show file tree
Hide file tree
Showing 31 changed files with 448 additions and 586 deletions.
27 changes: 24 additions & 3 deletions e2e/cypress/tests/08-aps-api/06-api-directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,21 @@ describe('API Tests for Updating dataset', () => {
})
})

it('Get the namespace directory details (/namespaces/{ns}/directory) and verify the success code in the response', () => {
it('Get the namespace directory details (/namespaces/{ns}/directory) and verify the success code and empty response for the namespace with no directory', () => {
cy.get('@apiowner').then(({ apiTest }: any) => {
cy.get('@api').then(({ apiDirectory }: any) => {
cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/directory', 'GET').then((res) => {
expect(res.status).to.be.equal(200)
expect(res.body).to.be.empty
})
})
})
})

it('Get the namespace directory details (/namespaces/{ns}/directory) and verify the success code in the response', () => {
cy.get('@apiowner').then(({ namespace }: any) => {
cy.get('@api').then(({ apiDirectory }: any) => {
cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory', 'GET').then((res) => {
expect(res.status).to.be.equal(200)
response = res.body[0]
directoryID = res.body[0].id
Expand All @@ -180,16 +191,26 @@ describe('API Tests for Updating dataset', () => {
// })

it('Get the namespace directory details by its ID (/namespaces/{ns}/directory/{id}) and verify the success code in the response', () => {
cy.get('@apiowner').then(({ apiTest }: any) => {
cy.get('@apiowner').then(({ namespace }: any) => {
cy.get('@api').then(({ apiDirectory }: any) => {
cy.makeAPIRequest(apiDirectory.endPoint + '/' + apiTest.namespace + '/directory' + '/' + directoryID, 'GET').then((res) => {
cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory' + '/' + directoryID, 'GET').then((res) => {
expect(res.status).to.be.equal(200)
expect(res.body.name).to.be.equal(directoryName)
})
})
})
})

it('Get the namespace directory details (/namespaces/{ns}/directory/{id}) for non exist directory ID and verify the response code', () => {
cy.get('@apiowner').then(({ namespace }: any) => {
cy.get('@api').then(({ apiDirectory }: any) => {
cy.makeAPIRequest(apiDirectory.endPoint + '/' + namespace + '/directory' + '/99' , 'GET').then((res) => {
expect(res.status).to.be.oneOf([404,422])
})
})
})
})

it('Delete the dataset (/organizations/{org}/datasets/{name}) and verify the success code in the response', () => {
cy.get('@apiowner').then(({ apiTest }: any) => {
cy.get('@api').then(({ apiDirectory, organization }: any) => {
Expand Down
84 changes: 43 additions & 41 deletions src/admin-hooks.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,44 @@


const HelloPage = require.resolve('./pages/hello')
const Placeholder = require.resolve('./pages/placeholder')

module.exports = {
pages: [
{
label: 'Dashboard',
path: '',
component: Placeholder,
},
{
label: 'Workflow',
children: ['AccessRequest', 'Application', 'ServiceAccess', 'Activity'],
},
{
label: 'Products',
children: ['Product', 'Environment', 'CredentialIssuer', 'Content', 'Legal'],
},
{
label: 'Monitoring',
children: ['Alert', 'Metric'],
},
{
label: 'Session',
children: ['TemporaryIdentity'],
},
{
label: 'Keycloak',
children: ['User'],
},
{
label: 'Kong',
children: ['GatewayService', 'GatewayRoute', 'GatewayConsumer', 'GatewayGroup', 'GatewayPlugin'],
},
{
label: 'BCDC',
children: ['Organization', 'OrganizationUnit', 'Dataset'],
}
]
}
pages: [
{
label: 'Workflow',
children: ['AccessRequest', 'Application', 'ServiceAccess', 'Activity'],
},
{
label: 'Products',
children: [
'Product',
'Environment',
'CredentialIssuer',
'Content',
'Legal',
],
},
{
label: 'Monitoring',
children: ['Alert', 'Metric'],
},
{
label: 'Session',
children: ['TemporaryIdentity'],
},
{
label: 'Keycloak',
children: ['User'],
},
{
label: 'Kong',
children: [
'GatewayService',
'GatewayRoute',
'GatewayConsumer',
'GatewayGroup',
'GatewayPlugin',
],
},
{
label: 'BCDC',
children: ['Organization', 'OrganizationUnit', 'Dataset'],
},
],
};
27 changes: 15 additions & 12 deletions src/api-openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,26 @@ class ApiOpenapiApp {
code: err.code,
message: err.message,
});
}
if (err instanceof ValidateError) {
} else if (err instanceof ValidateError) {
console.warn(`Caught Validation Error for ${req.path}:`, err.fields);
return res.status(422).json({
message: 'Validation Failed',
details: err?.fields,
});
}
if (err instanceof AssertionError) {
logger.error(err);
logger.error('AssertionError PATH: %s', req.path);
return res.status(422).json({
message: err.message,
});
}

if (err instanceof Error) {
} else if (err instanceof AssertionError) {
// For some reason `message` is what the `stack` is normally
// so just grab the first line and return that
const response = {
message: 'Failed an assertion',
};
try {
logger.warn('Error message %s', err.message);
response.message = err.message.split('\n')[0];
} catch (e) {
logger.warn('Failed to parse error message %s', e);
}
return res.status(422).json(response);
} else if (err instanceof Error) {
logger.error(err);
logger.error('Error PATH: %s', req.path);
return res.status(500).json({
Expand Down
4 changes: 2 additions & 2 deletions src/auth/auth-oauth2-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ class Oauth2ProxyAuthStrategy {
try {
const rpt = jwtDecoder(accessToken);
const jti = req['oauth_user']['jti']; // JWT ID - Unique Identifier for the token
const username = req['oauth_user']['preferred_username']; // Username included in token
const identityProvider = req['oauth_user']['identity_provider']; // Identity Provider included in token
// The oauth2_proxy is handling the refresh token; so there can be a new jti
logger.info(
'[ns-switch] %s -> %s : %s',
Expand All @@ -239,7 +239,7 @@ class Oauth2ProxyAuthStrategy {
await this.assign_namespace(
req.user.jti,
jti,
username,
identityProvider,
rpt['authorization']['permissions'][0]
);
res.json({ switch: true });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

query GetBusinessProfile($consumerId: ID!) {
BusinessProfile(serviceAccessId: $consumerId) {
institution {
legalName
address {
addressLine1
addressLine2
city
postal
province
country
}
isSuspended
businessTypeOther
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

query GetBusinessProfile($consumerId: ID!) {
BusinessProfile(consumerId: $consumerId) {
institution {
legalName
address {
addressLine1
addressLine2
city
postal
province
country
}
isSuspended
businessTypeOther
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

query GetAccessRequests {
allAccessRequestsByNamespace(where: { isComplete_not: true }) {
id
name
additionalDetails
communication
createdAt
requestor {
name
}
application {
name
}
productEnvironment {
id
name
additionalDetailsToRequest
product {
name
}
}
serviceAccess {
consumer {
id
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

query RequestDetailsBusinessProfile($consumerId: ID!) {
BusinessProfile(consumerId: $consumerId) {
institution {
legalName
address {
addressLine1
addressLine2
city
postal
province
country
}
}
}
}
10 changes: 4 additions & 6 deletions src/authz/matrix.csv
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ NS MANAGER,,getNamespaceConsumerAccess,,,,,,,api-owner,,,allow,
NS MANAGER,,allConsumerGroupLabels,,,,,,,api-owner,,,allow,
NS MANAGER,,allConsumerScopesAndRoles,,,,,,,api-owner,,,allow,
NS MANAGER,,getConsumerProdEnvAccess,,,,,,,api-owner,,,allow,
NS MANAGER,,allProductsByNamespace,,,,,,,api-owner,,,allow,
NS MANAGER,,allGatewayServicesByNamespace,,,,,,,api-owner,,,allow,
NS MANAGER,,getFilteredNamespaceConsumers,,,,,,,api-owner,,,allow,
NS MANAGER,,allProductsByNamespace,,,,,,,api-owner,,,allow,filterByUserNS
NS MANAGER,,allGatewayServicesByNamespace,,,,,,,api-owner,,,allow,filterByUserNS
NS MANAGER,,getFilteredNamespaceConsumers,,,,,,,api-owner,,,allow,filterByUserNS
API Owner Role Rules,,,AccessRequest,read,,,,,,,"api-owner,provider-user",allow,
API Owner Role Rules,,,Activity,read,,,,,,,"api-owner,provider-user",allow,filterByUserNS
API Owner Role Rules,,,Alert,,read,,,,,,"api-owner,provider-user",allow,
Expand All @@ -87,7 +87,6 @@ API Owner Role Rules,,forceDeleteEnvironment,,,,,,,api-owner,,,allow,
API Owner Role Rules,,,Environment,read,,,,,,,"api-owner,provider-user",allow,
API Owner Role Rules,,,Environment,create,,,,,api-owner,,,allow,
API Owner Role Rules,,,Environment,update,,,,,api-owner,,,allow,
,,,,,,,,,,,,,
API Owner Role Rules,,,Label,read,,,,,api-owner,,,allow,
API Owner Role Rules,,,GatewayConsumer,,"read,update,delete",,,,api-owner,,,allow,
API Owner Role Rules,,,GatewayConsumer,create,,,,,api-owner,,,allow,
Expand Down Expand Up @@ -199,8 +198,7 @@ API Owner Role Rules,,allGatewayRoutesByNamespace,,,,,,,,,"api-owner,provider-us
API Owner Role Rules,,allProductsByNamespace,,,,,,,,,"api-owner,provider-user",allow,filterByUserNS
API Owner Role Rules,,allNamespaceServiceAccounts,,,,,,,,,"api-owner,provider-user",allow,filterByUserNS
API Owner Role Rules,,allCredentialIssuersByNamespace,,,,,,,,,"api-owner,provider-user",allow,filterByUserNS
,,allProductsByNamespace,,,,,,,,,portal-user,allow,
,,,,,,,,,,,,,
Portal User or Guest,,allProductsByNamespace,,,,,,,,,portal-user,allow,filterByUserNS
Portal User or Guest,,allDiscoverableContents,,,,,,,,,"portal-user,guest",allow,filterByNamespaceOrPublic
Portal User or Guest,,allDiscoverableProducts,,,,,,,,,"portal-user,guest",allow,filterByActiveEnvironment
Portal User or Guest,,allProducts,,,,,,,,,"portal-user,guest",allow,
Expand Down
9 changes: 6 additions & 3 deletions src/controllers/v2/NamespaceDirectoryController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { KeystoneService } from '../ioc/keystoneInjector';
import { inject, injectable } from 'tsyringe';
import { transform, transformSetAnonymous } from './DirectoryController';
import { gql } from 'graphql-request';
import { strict as assert } from 'assert';

@injectable()
@Route('/namespaces/{ns}/directory')
Expand Down Expand Up @@ -47,9 +48,11 @@ export class NamespaceDirectoryController extends Controller {
variables: { id },
});

if (result.data.allProductsByNamespace.length == 0) {
return null;
}
assert.strictEqual(
result.data.allProductsByNamespace?.length === 1,
true,
'Dataset not found'
);

return transform(
transformSetAnonymous(result.data.allProductsByNamespace)
Expand Down
30 changes: 13 additions & 17 deletions src/lists/extensions/BusinessProfile.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { EnforcementPoint } from '../../authz/enforcement';

import { lookupCredentialReferenceByServiceAccess } from '../../services/keystone';

import { ConfigService } from '../../services/config.service';
import { BCeIDService } from '../../services/bceid/bceid.service';
import { getNamespaceConsumerAccess } from '../../services/workflow';
import { Logger } from '../../logger';

const logger = Logger('List.Ext.BusProfile');

const typeBusinessProfile = `
type BusinessProfile {
Expand Down Expand Up @@ -58,29 +59,24 @@ module.exports = {
],
queries: [
{
schema: 'BusinessProfile(serviceAccessId: ID!): BusinessProfile',
schema: 'BusinessProfile(consumerId: ID!): BusinessProfile',
resolver: async (
item: any,
args: any,
{ consumerId }: any,
context: any,
info: any,
{ query, access }: any
) => {
const serviceAccess = await lookupCredentialReferenceByServiceAccess(
const namespace = context.req.user.namespace;
const consumer = await getNamespaceConsumerAccess(
context,
args.serviceAccessId
namespace,
consumerId
);
logger.debug('%s -> %j', consumerId, consumer.owner);

const fullUsername = serviceAccess.application?.owner.username;

if (
fullUsername != null &&
fullUsername.endsWith('@bceid-business')
) {
const username = fullUsername.substring(
0,
fullUsername.lastIndexOf('@')
);
if (consumer.owner?.provider === 'bceid-business') {
const username = consumer.owner?.providerUsername;

const bc = new BCeIDService(new ConfigService());
return await bc.getAccountDetails(username);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ const query = gql`
name
}
}
serviceAccess {
consumer {
id
}
}
}
}
`;
Loading

0 comments on commit 3ae1d2b

Please sign in to comment.