47 lines
2.9 KiB
TypeScript
47 lines
2.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { bsiConsistency, bsiConsistencyFingerprintSource } from '../../src/compliance/bsi-consistency';
|
|
import type { BsiIsoCrosswalk } from '../../src/compliance/bsi-grundschutz';
|
|
|
|
// Synthetic BSI mapping: two ISO controls reach three requirements; SYN.9.1 is reachable from no ISO control.
|
|
const crosswalk: BsiIsoCrosswalk = {
|
|
schemaVersion: 1, framework: 'bsi-iso27001-annex-a-to-grundschutz-plus-plus', title: 'Synthetic', version: '0.1-synthetic',
|
|
sourceUrl: 'https://example.invalid/synthetic', sourceSha256: '0'.repeat(64), license: 'Synthetic', targetCatalog: 'synthetic',
|
|
entries: [
|
|
{ uuid: 'a', isoControlId: '8.9', relationship: 'subset-of', targets: ['KONF.1.1', 'KONF.2.1'] },
|
|
{ uuid: 'b', isoControlId: '5.15', relationship: 'equivalent-to', targets: ['BER.3.5'] }
|
|
]
|
|
};
|
|
|
|
describe('ISO <-> BSI consistency', () => {
|
|
it('has nothing to compare while no BSI requirement is accepted directly', () => {
|
|
expect(bsiConsistency(['8.9'], [], crosswalk)).toBeUndefined();
|
|
});
|
|
|
|
it('is consistent when one direct requirement lies in the set derived from the accepted ISO controls', () => {
|
|
// subset-of reaches two requirements; one hit is enough, and an extra direct requirement does not break it.
|
|
expect(bsiConsistency(['8.9'], ['KONF.2.1', 'SYN.9.1'], crosswalk)).toMatchObject({
|
|
state: 'consistent', overlapRequirementIds: ['KONF.2.1'], unreachableRequirementIds: ['SYN.9.1'],
|
|
derivedRequirementIds: ['KONF.1.1', 'KONF.2.1'], reverseCandidates: []
|
|
});
|
|
});
|
|
|
|
it('is inconsistent when a reachable direct requirement is not derived, and names the ISO control the BSI mapping points to', () => {
|
|
expect(bsiConsistency(['8.9'], ['BER.3.5'], crosswalk)).toMatchObject({
|
|
state: 'inconsistent', overlapRequirementIds: [], reverseCandidates: [{ isoControlId: '5.15', requirementIds: ['BER.3.5'] }]
|
|
});
|
|
// Without any accepted ISO control, a reachable direct requirement is a disagreement as well.
|
|
expect(bsiConsistency([], ['KONF.1.1'], crosswalk)?.state).toBe('inconsistent');
|
|
});
|
|
|
|
it('reports no ISO reference when no direct requirement is reachable from any ISO control', () => {
|
|
expect(bsiConsistency(['8.9'], ['SYN.9.1'], crosswalk)).toMatchObject({ state: 'no-reference', unreachableRequirementIds: ['SYN.9.1'], reverseCandidates: [] });
|
|
});
|
|
|
|
it('fingerprints the compared sets independent of order, and changes with a decision or the mapping version', () => {
|
|
const base = bsiConsistencyFingerprintSource(['8.9', '5.15'], ['BER.3.5', 'KONF.1.1'], '0.1');
|
|
expect(bsiConsistencyFingerprintSource(['5.15', '8.9', '8.9'], ['KONF.1.1', 'BER.3.5'], '0.1')).toBe(base);
|
|
expect(bsiConsistencyFingerprintSource(['8.9'], ['BER.3.5', 'KONF.1.1'], '0.1')).not.toBe(base);
|
|
expect(bsiConsistencyFingerprintSource(['8.9', '5.15'], ['BER.3.5', 'KONF.1.1'], '0.2')).not.toBe(base);
|
|
});
|
|
});
|