mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 04:27:02 +01:00
Adjust output of claim maps for better parsing (#2566)
* Adjust output of claim maps for better parsing * Update python tests for OAuth2 bits * fixing workflows for container builds --------- Co-authored-by: James Hodgkinson <james@terminaloutcomes.com>
This commit is contained in:
parent
1a6400b58e
commit
adb575947f
16
.github/workflows/docker_build_kanidm.yml
vendored
16
.github/workflows/docker_build_kanidm.yml
vendored
|
@ -12,9 +12,22 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
set_lower_case_name:
|
||||
runs-on: ubuntu-latest
|
||||
name: set lower case owner name
|
||||
steps:
|
||||
- id: step1
|
||||
run: |
|
||||
echo "OWNER_LC=${OWNER,,}" >> "${GITHUB_OUTPUT}"
|
||||
env:
|
||||
OWNER: '${{ github.repository_owner }}'
|
||||
outputs:
|
||||
owner_lc: ${{ steps.step1.outputs.OWNER_LC }}
|
||||
|
||||
kanidm_build:
|
||||
name: Build kanidm Docker image
|
||||
runs-on: ubuntu-latest
|
||||
needs: set_lower_case_name
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
|
@ -23,7 +36,8 @@ jobs:
|
|||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
platforms: "linux/amd64"
|
||||
tags: ghcr.io/${{ github.repository_owner }}/kanidm:devel
|
||||
tags: ghcr.io/${{ needs.set_lower_case_name.outputs.owner_lc }}/kanidm:devel
|
||||
|
||||
build-args: |
|
||||
"KANIDM_FEATURES="
|
||||
# "KANIDM_BUILD_OPTIONS=-j1"
|
||||
|
|
15
.github/workflows/docker_build_kanidmd.yml
vendored
15
.github/workflows/docker_build_kanidmd.yml
vendored
|
@ -12,9 +12,22 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
set_lower_case_name:
|
||||
runs-on: ubuntu-latest
|
||||
name: set lower case owner name
|
||||
steps:
|
||||
- id: step1
|
||||
run: |
|
||||
echo "OWNER_LC=${OWNER,,}" >> "${GITHUB_OUTPUT}"
|
||||
env:
|
||||
OWNER: '${{ github.repository_owner }}'
|
||||
outputs:
|
||||
owner_lc: ${{ steps.step1.outputs.OWNER_LC }}
|
||||
|
||||
kanidmd_build:
|
||||
name: Build kanidmd Docker image
|
||||
runs-on: ubuntu-latest
|
||||
needs: set_lower_case_name
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
|
@ -41,7 +54,7 @@ jobs:
|
|||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
platforms: "linux/amd64"
|
||||
tags: ghcr.io/${{ github.repository_owner }}/kanidmd:devel
|
||||
tags: ghcr.io/${{ needs.set_lower_case_name.outputs.owner_lc }}/kanidmd:devel
|
||||
# build-args: |
|
||||
# "KANIDM_BUILD_OPTIONS=-j1"
|
||||
file: server/Dockerfile
|
||||
|
|
|
@ -1,11 +1,37 @@
|
|||
# pylint: disable=too-few-public-methods
|
||||
# ^ disabling this because pydantic models don't have public methods
|
||||
|
||||
import json
|
||||
from typing import Dict, List, TypedDict
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, RootModel
|
||||
|
||||
|
||||
class OAuth2RsClaimMap(BaseModel):
|
||||
name: str
|
||||
group: str
|
||||
join: str
|
||||
values: List[str]
|
||||
|
||||
@classmethod
|
||||
def from_entry(cls, entry: str) -> "OAuth2RsClaimMap":
|
||||
name, group, join, values = entry.split(":")
|
||||
values = json.loads(values).split(",")
|
||||
return cls(name=name, group=group, join=join, values=values)
|
||||
|
||||
|
||||
class OAuth2RsScopeMap(BaseModel):
|
||||
group: str
|
||||
values: List[str]
|
||||
|
||||
@classmethod
|
||||
def from_entry(cls, entry: str) -> "OAuth2RsScopeMap":
|
||||
group, values = entry.split(":")
|
||||
values = values.replace("{", "[").replace("}", "]")
|
||||
values = json.loads(values.strip())
|
||||
return cls(group=group, values=values)
|
||||
|
||||
|
||||
class OAuth2Rs(BaseModel):
|
||||
classes: List[str]
|
||||
displayname: str
|
||||
|
@ -14,7 +40,9 @@ class OAuth2Rs(BaseModel):
|
|||
oauth2_rs_basic_secret: str
|
||||
oauth2_rs_origin: str
|
||||
oauth2_rs_token_key: str
|
||||
oauth2_rs_sup_scope_map: List[str]
|
||||
oauth2_rs_scope_map: List[OAuth2RsScopeMap]
|
||||
oauth2_rs_sup_scope_map: List[OAuth2RsScopeMap]
|
||||
oauth2_rs_claim_map: List[OAuth2RsClaimMap]
|
||||
|
||||
|
||||
class RawOAuth2Rs(BaseModel):
|
||||
|
@ -38,6 +66,19 @@ class RawOAuth2Rs(BaseModel):
|
|||
if len(self.attrs[field]) == 0:
|
||||
raise ValueError(f"Empty field {field} in {self.attrs}")
|
||||
|
||||
oauth2_rs_scope_map = [
|
||||
OAuth2RsScopeMap.from_entry(entry)
|
||||
for entry in self.attrs.get("oauth2_rs_scope_map", [])
|
||||
]
|
||||
oauth2_rs_sup_scope_map = [
|
||||
OAuth2RsScopeMap.from_entry(entry)
|
||||
for entry in self.attrs.get("oauth2_rs_sup_scope_map", [])
|
||||
]
|
||||
oauth2_rs_claim_map = [
|
||||
OAuth2RsClaimMap.from_entry(entry)
|
||||
for entry in self.attrs.get("oauth2_rs_claim_map", [])
|
||||
]
|
||||
|
||||
return OAuth2Rs(
|
||||
classes=self.attrs["class"],
|
||||
displayname=self.attrs["displayname"][0],
|
||||
|
@ -46,9 +87,12 @@ class RawOAuth2Rs(BaseModel):
|
|||
oauth2_rs_basic_secret=self.attrs["oauth2_rs_basic_secret"][0],
|
||||
oauth2_rs_origin=self.attrs["oauth2_rs_origin"][0],
|
||||
oauth2_rs_token_key=self.attrs["oauth2_rs_token_key"][0],
|
||||
oauth2_rs_sup_scope_map=self.attrs.get("oauth2_rs_sup_scope_map", []),
|
||||
oauth2_rs_scope_map=oauth2_rs_scope_map,
|
||||
oauth2_rs_sup_scope_map=oauth2_rs_sup_scope_map,
|
||||
oauth2_rs_claim_map=oauth2_rs_claim_map,
|
||||
)
|
||||
|
||||
|
||||
Oauth2RsList = RootModel[List[RawOAuth2Rs]]
|
||||
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ load-plugins = "pylint_pydantic,pylint_pytest"
|
|||
[tool.ruff]
|
||||
line-length = 150
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/*.py" = [
|
||||
"F401", # unused import, reused fixtures across all tests
|
||||
"F811", # pytest fixtures
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import json
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from kanidm import KanidmClient
|
||||
|
@ -23,9 +24,12 @@ async def test_oauth2_rs_list(client: KanidmClient) -> None:
|
|||
logging.basicConfig(level=logging.DEBUG)
|
||||
print(f"config: {client.config}")
|
||||
|
||||
username = "admin"
|
||||
# change this to be your admin password.
|
||||
password = "pdf1Xz8q2QFsMTsvbv2jXNBaSEsDpW9h83ZRsH7dDfsJeJdM"
|
||||
username = "idm_admin"
|
||||
# change this to be the password.
|
||||
password = os.getenv("KANIDM_PASSWORD")
|
||||
if password is None:
|
||||
print("No KANIDM_PASSWORD env var set for testing")
|
||||
raise pytest.skip("No KANIDM_PASSWORD env var set for testing")
|
||||
|
||||
auth_resp = await client.authenticate_password(
|
||||
username, password, update_internal_auth_token=True
|
||||
|
@ -41,13 +45,9 @@ async def test_oauth2_rs_list(client: KanidmClient) -> None:
|
|||
|
||||
resource_servers = await client.oauth2_rs_list()
|
||||
print("content:")
|
||||
print(json.dumps(resource_servers, indent=4))
|
||||
|
||||
if resource_servers:
|
||||
for oauth_rs in resource_servers:
|
||||
print(json.dumps(oauth_rs.model_dump(), indent=4, default=str))
|
||||
for mapping in oauth_rs.oauth2_rs_sup_scope_map:
|
||||
print(f"oauth2_rs_sup_scope_map: {mapping}")
|
||||
user, scopes = mapping.split(":")
|
||||
scopes = scopes.replace("{", "[").replace("}", "]")
|
||||
scopes = json.loads(scopes)
|
||||
print(f"{user=} {scopes=}")
|
||||
|
|
|
@ -126,6 +126,9 @@ ${KANIDM} system oauth2 update-scope-map "${OAUTH2_RP_ID}" "${TEST_GROUP}" openi
|
|||
echo "Creating the ${OAUTH2_RP_ID} OAuth2 RP Supplemental Scope Map"
|
||||
${KANIDM} system oauth2 update-sup-scope-map "${OAUTH2_RP_ID}" "${TEST_GROUP}" admin -D "${IDM_ADMIN_USER}"
|
||||
|
||||
echo "Creating a claim map for RS ${OAUTH2_RP_ID}"
|
||||
${KANIDM} system oauth2 update-claim-map "${OAUTH2_RP_ID}" testclaim "${TEST_GROUP}" foo bar
|
||||
|
||||
echo "Creating the OAuth2 RP Secondary Supplemental Crab-baite Scope Map.... wait, no that's not a thing."
|
||||
|
||||
echo "Checking the OAuth2 RP Exists"
|
||||
|
|
|
@ -764,6 +764,27 @@ pub trait QueryServerTransaction<'a> {
|
|||
})
|
||||
.collect();
|
||||
v
|
||||
} else if let Some(r_map) = value.as_oauthclaim_map() {
|
||||
let mut v = Vec::new();
|
||||
for (claim_name, mapping) in r_map.iter() {
|
||||
for (group_ref, claims) in mapping.values() {
|
||||
let join_char = mapping.join().to_char();
|
||||
|
||||
let nv = self.uuid_to_spn(*group_ref)?;
|
||||
let resolved_id = match nv {
|
||||
Some(v) => v.to_proto_string_clone(),
|
||||
None => uuid_to_proto_string(*group_ref),
|
||||
};
|
||||
|
||||
let joined = str_concat!(claims, ',');
|
||||
|
||||
v.push(format!(
|
||||
"{}:{}:{}:{:?}",
|
||||
claim_name, resolved_id, join_char, joined
|
||||
))
|
||||
}
|
||||
}
|
||||
Ok(v)
|
||||
} else {
|
||||
let v: Vec<_> = value.to_proto_string_clone_iter().collect();
|
||||
Ok(v)
|
||||
|
|
|
@ -1000,6 +1000,17 @@ pub enum OauthClaimMapJoin {
|
|||
JsonArray,
|
||||
}
|
||||
|
||||
impl OauthClaimMapJoin {
|
||||
pub(crate) fn to_char(&self) -> char {
|
||||
match self {
|
||||
OauthClaimMapJoin::CommaSeparatedValue => ',',
|
||||
OauthClaimMapJoin::SpaceSeparatedValue => ' ',
|
||||
// Should this be something else?
|
||||
OauthClaimMapJoin::JsonArray => ';',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DbValueOauthClaimMapJoinV1> for OauthClaimMapJoin {
|
||||
fn from(value: DbValueOauthClaimMapJoinV1) -> OauthClaimMapJoin {
|
||||
match value {
|
||||
|
|
|
@ -368,7 +368,6 @@ pub trait ValueSetT: std::fmt::Debug + DynClone {
|
|||
}
|
||||
|
||||
fn as_oauthclaim_map(&self) -> Option<&BTreeMap<String, OauthClaimMapping>> {
|
||||
debug_assert!(false);
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -637,12 +637,7 @@ impl ValueSetT for ValueSetOauthClaimMap {
|
|||
fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
|
||||
Box::new(self.map.iter().flat_map(|(name, mapping)| {
|
||||
mapping.values.iter().map(move |(group, claims)| {
|
||||
let join_char = match mapping.join {
|
||||
OauthClaimMapJoin::CommaSeparatedValue => ',',
|
||||
OauthClaimMapJoin::SpaceSeparatedValue => ' ',
|
||||
// Should this be something else?
|
||||
OauthClaimMapJoin::JsonArray => ';',
|
||||
};
|
||||
let join_char = mapping.join.to_char();
|
||||
|
||||
let joined = str_concat!(claims, join_char);
|
||||
|
||||
|
|
Loading…
Reference in a new issue