Skip to content

Commit

Permalink
Add OIDC ABAC roles mapping type guard
Browse files Browse the repository at this point in the history
Make sure the OIDC ABAC roles mapping configuration matches the expected
type after it's parsed from the JSON string.
  • Loading branch information
jraddaoui committed Oct 22, 2024
1 parent 00dd08c commit 4a6578c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 6 deletions.
34 changes: 32 additions & 2 deletions dashboard/src/stores/__tests__/auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,15 +262,45 @@ describe("useAuthStore", () => {
},
},
},
{
title: "invalid roles mapping",
stubEnv: {
VITE_OIDC_ABAC_ROLES_MAPPING: '{"admin": ["*"}',
},
error:
"Error parsing OIDC ABAC roles mapping: SyntaxError: Expected ',' or ']' after array element in JSON at position 14 (line 1 column 15)",
},
{
title: "not array roles mapping",
stubEnv: {
VITE_OIDC_ABAC_ROLES_MAPPING: '{"admin": ["*"], "other": "not array"}',
},
error:
"Error parsing OIDC ABAC roles mapping: unexpected JSON format, each role key must be an array of string attributes",
},
{
title: "not strings roles mapping",
stubEnv: {
VITE_OIDC_ABAC_ROLES_MAPPING: '{"admin": ["string", 1]}',
},
error:
"Error parsing OIDC ABAC roles mapping: unexpected JSON format, each role key must be an array of string attributes",
},
])("loads the configuration from the environment ($title)", (test) => {
if (test.stubEnv) {
Object.entries(test.stubEnv).forEach(([key, value]) =>
vi.stubEnv(key, value),
);
}

const authStore = useAuthStore();
authStore.loadConfig();
expect(authStore.config).toEqual(test.expected);
if (test.error) {
assert.throws(authStore.loadConfig, test.error);
} else {
authStore.loadConfig();
expect(authStore.config).toEqual(test.expected);
}

vi.unstubAllEnvs();
});

Expand Down
23 changes: 19 additions & 4 deletions dashboard/src/stores/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ type ABACConfig = {
rolesMapping: Record<string, string[]>;
};

function isRolesMapping(obj: any): obj is Record<string, string[]> {
for (const key in obj) {
if (
!Array.isArray(obj[key]) ||
!obj[key].every((item) => typeof item === "string")
)
return false;
}
return true;
}

export const useAuthStore = defineStore("auth", {
state: () => ({
config: {} as OIDCConfig,
Expand Down Expand Up @@ -142,11 +153,15 @@ export const useAuthStore = defineStore("auth", {
}
if (this.config.abac.useRoles && env.VITE_OIDC_ABAC_ROLES_MAPPING) {
try {
this.config.abac.rolesMapping = JSON.parse(
env.VITE_OIDC_ABAC_ROLES_MAPPING.trim(),
);
const map = JSON.parse(env.VITE_OIDC_ABAC_ROLES_MAPPING.trim());
if (!isRolesMapping(map)) {
throw new Error(
"Error parsing OIDC ABAC roles mapping: unexpected JSON format, each role key must be an array of string attributes",
);
}
this.config.abac.rolesMapping = map;
} catch (err) {
throw new Error(`Error parsing roles mapping: ${err}`);
throw new Error(`Error parsing OIDC ABAC roles mapping: ${err}`);
}
}
},
Expand Down

0 comments on commit 4a6578c

Please sign in to comment.