Skip to content

Commit 142e73d

Browse files
authored
Merge pull request #177 from himmelblau-idm/dmulder/dbus_broker_service
Add the D-Bus broker service
2 parents 4f80ab0 + ae93948 commit 142e73d

21 files changed

+498
-55
lines changed

.github/workflows/build.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ jobs:
4747
libpcre2-dev \
4848
libclang-13-dev \
4949
autoconf \
50-
gettext
50+
gettext \
51+
libdbus-1-dev
5152
5253
- name: "Fetch submodules"
5354
run: git submodule init && git submodule update

.github/workflows/build_debian_source_package.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ jobs:
5555
pkgconf \
5656
debhelper-compat \
5757
devscripts \
58-
libclang-14-dev
58+
libclang-14-dev \
59+
libdbus-1-dev
5960
6061
- name: "[general] - Fetch submodules"
6162
run: |

.github/workflows/clippy.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ jobs:
4747
libpcre2-dev \
4848
libclang-13-dev \
4949
autoconf \
50-
gettext
50+
gettext \
51+
libdbus-1-dev
5152
5253
- name: "Fetch submodules"
5354
run: git submodule init && git submodule update

.github/workflows/test.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ jobs:
4747
libpcre2-dev \
4848
libclang-13-dev \
4949
autoconf \
50-
gettext
50+
gettext \
51+
libdbus-1-dev
5152
5253
- name: "Fetch submodules"
5354
run: git submodule init && git submodule update

Cargo.toml

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ members = [
1212
"src/users",
1313
"src/idmap",
1414
"src/file_permissions",
15+
"src/broker",
1516
]
1617
resolver = "2"
1718

1819
[workspace.package]
19-
version = "0.5.0"
20+
version = "0.6.0"
2021
authors = [
2122
"David Mulder <[email protected]>"
2223
]
@@ -37,12 +38,12 @@ tracing-subscriber = "^0.3.17"
3738
tracing = "^0.1.37"
3839
himmelblau_unix_common = { path = "src/common" }
3940
kanidm_unix_common = { path = "src/glue" }
40-
libhimmelblau = { version = "0.2.9" }
41+
libhimmelblau = { version = "0.3.0" }
4142
clap = { version = "^4.5", features = ["derive", "env"] }
4243
clap_complete = "^4.4.1"
4344
reqwest = { version = "^0.12.2", features = ["json"] }
4445
anyhow = "^1.0.71"
45-
tokio = { version = "^1.28.1", features = ["rt", "macros", "sync", "time", "net", "io-util", "signal"] }
46+
tokio = { version = "^1.28.1", features = ["rt", "macros", "sync", "time", "net", "io-util", "signal", "rt-multi-thread"] }
4647
tokio-util = { version = "^0.7.8", features = ["codec"] }
4748
async-trait = "^0.1.72"
4849
pem = "^3.0.2"
@@ -51,6 +52,7 @@ os-release = "^0.1.0"
5152
jsonwebtoken = "^9.2.0"
5253
zeroize = "^1.7.0"
5354
idmap = { path = "src/idmap" }
55+
identity_dbus_broker = "0.1.0"
5456

5557
# Kanidm deps
5658
argon2 = { version = "0.5.2", features = ["alloc"] }
@@ -76,7 +78,7 @@ tracing-forest = "^0.1.6"
7678
rusqlite = "^0.32.0"
7779
hashbrown = { version = "0.14.0", features = ["serde", "inline-more", "ahash"] }
7880
lru = "^0.12.3"
79-
kanidm_lib_crypto = { path = "./src/crypto", version = "0.5.0" }
81+
kanidm_lib_crypto = { path = "./src/crypto", version = "0.6.0" }
8082
kanidm_utils_users = { path = "./src/users" }
8183
walkdir = "2"
8284
csv = "1.2.2"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[D-BUS Service]
2+
Name=com.microsoft.identity.broker1
3+
Exec=/usr/sbin/broker

platform/debian/himmelblaud.service

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ Description=Himmelblau Authentication Daemon
66
After=chronyd.service ntpd.service network-online.target
77

88
[Service]
9+
BusName=org.samba.himmelblau
910
DynamicUser=yes
1011
UMask=0027
1112
CacheDirectory=himmelblaud # /var/cache/himmelblaud
1213
RuntimeDirectory=himmelblaud # /run/himmelblaud
1314
StateDirectory=himmelblaud # /var/lib/himmelblaud
1415

15-
Type=simple
16+
Type=dbus
1617
ExecStart=/usr/sbin/himmelblaud
1718

1819
# Implied by dynamic user.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2+
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
3+
<busconfig>
4+
<policy context="default">
5+
<allow own="org.samba.himmelblau"/>
6+
<allow send_destination="org.samba.himmelblau"/>
7+
</policy>
8+
</busconfig>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[D-BUS Service]
2+
Name=com.microsoft.identity.broker1
3+
Exec=/usr/sbin/broker

platform/opensuse/himmelblaud.service

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ Description=Himmelblau Authentication Daemon
66
After=chronyd.service ntpd.service network-online.target suspend.target
77

88
[Service]
9+
BusName=org.samba.himmelblau
910
DynamicUser=yes
1011
UMask=0027
1112
CacheDirectory=himmelblaud # /var/cache/himmelblaud
1213
RuntimeDirectory=himmelblaud # /run/himmelblaud
1314
StateDirectory=himmelblaud # /var/lib/himmelblaud
1415

15-
Type=simple
16+
Type=dbus
1617
ExecStart=/usr/sbin/himmelblaud
1718

1819
# Implied by dynamic user.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2+
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
3+
<busconfig>
4+
<policy context="default">
5+
<allow own="org.samba.himmelblau"/>
6+
<allow send_destination="org.samba.himmelblau"/>
7+
</policy>
8+
</busconfig>

src/broker/Cargo.toml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "broker"
3+
version.workspace = true
4+
authors.workspace = true
5+
rust-version.workspace = true
6+
edition.workspace = true
7+
license.workspace = true
8+
homepage.workspace = true
9+
repository.workspace = true
10+
11+
[dependencies]
12+
dbus = "0.9.7"
13+
identity_dbus_broker.workspace = true
14+
tokio.workspace = true

src/broker/src/main.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
Unix Azure Entra ID implementation
3+
Copyright (C) David Mulder <[email protected]> 2024
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
use identity_dbus_broker::himmelblau_session_broker_serve;
19+
20+
#[tokio::main]
21+
async fn main() -> Result<(), dbus::MethodErr> {
22+
himmelblau_session_broker_serve().await
23+
}

src/common/src/db.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ mod tests {
10931093
uuid: uuid::uuid!("0302b99c-f0f6-41ab-9492-852692b0fd16"),
10941094
shell: None,
10951095
groups: Vec::new(),
1096-
sshkeys: vec!["key-a".to_string()],
1096+
tenant_id: uuid::uuid!("58e8a301-2502-4814-81c5-a4d17c399a45"),
10971097
valid: true,
10981098
};
10991099

@@ -1266,7 +1266,7 @@ mod tests {
12661266
uuid: uuid::uuid!("0302b99c-f0f6-41ab-9492-852692b0fd16"),
12671267
shell: None,
12681268
groups: vec![gt1.clone(), gt2],
1269-
sshkeys: vec!["key-a".to_string()],
1269+
tenant_id: uuid::uuid!("58e8a301-2502-4814-81c5-a4d17c399a45"),
12701270
valid: true,
12711271
};
12721272

@@ -1335,7 +1335,7 @@ mod tests {
13351335
uuid: uuid1,
13361336
shell: None,
13371337
groups: Vec::new(),
1338-
sshkeys: vec!["key-a".to_string()],
1338+
tenant_id: uuid::uuid!("58e8a301-2502-4814-81c5-a4d17c399a45"),
13391339
valid: true,
13401340
};
13411341

@@ -1459,7 +1459,7 @@ mod tests {
14591459
uuid: uuid::uuid!("0302b99c-f0f6-41ab-9492-852692b0fd16"),
14601460
shell: None,
14611461
groups: Vec::new(),
1462-
sshkeys: vec!["key-a".to_string()],
1462+
tenant_id: uuid::uuid!("58e8a301-2502-4814-81c5-a4d17c399a45"),
14631463
valid: true,
14641464
};
14651465

@@ -1471,7 +1471,7 @@ mod tests {
14711471
uuid: uuid::uuid!("799123b2-3802-4b19-b0b8-1ffae2aa9a4b"),
14721472
shell: None,
14731473
groups: Vec::new(),
1474-
sshkeys: vec!["key-a".to_string()],
1474+
tenant_id: uuid::uuid!("58e8a301-2502-4814-81c5-a4d17c399a45"),
14751475
valid: true,
14761476
};
14771477

src/common/src/idprovider/himmelblau.rs

+118-3
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,61 @@ impl IdProvider for HimmelblauMultiProvider {
149149
Ok(())
150150
}
151151

152+
async fn unix_user_access(
153+
&self,
154+
id: &Id,
155+
scopes: Vec<String>,
156+
old_token: Option<&UserToken>,
157+
tpm: &mut tpm::BoxedDynTpm,
158+
machine_key: &tpm::MachineKey,
159+
) -> Result<UnixUserToken, IdpError> {
160+
let account_id = match old_token {
161+
Some(token) => token.spn.clone(),
162+
None => id.to_string().clone(),
163+
};
164+
match split_username(&account_id) {
165+
Some((_sam, domain)) => {
166+
let providers = self.providers.read().await;
167+
match providers.get(domain) {
168+
Some(provider) => {
169+
provider
170+
.unix_user_access(id, scopes, old_token, tpm, machine_key)
171+
.await
172+
}
173+
None => Err(IdpError::NotFound),
174+
}
175+
}
176+
None => Err(IdpError::NotFound),
177+
}
178+
}
179+
180+
async fn unix_user_prt_cookie(
181+
&self,
182+
id: &Id,
183+
old_token: Option<&UserToken>,
184+
tpm: &mut tpm::BoxedDynTpm,
185+
machine_key: &tpm::MachineKey,
186+
) -> Result<String, IdpError> {
187+
let account_id = match old_token {
188+
Some(token) => token.spn.clone(),
189+
None => id.to_string().clone(),
190+
};
191+
match split_username(&account_id) {
192+
Some((_sam, domain)) => {
193+
let providers = self.providers.read().await;
194+
match providers.get(domain) {
195+
Some(provider) => {
196+
provider
197+
.unix_user_prt_cookie(id, old_token, tpm, machine_key)
198+
.await
199+
}
200+
None => Err(IdpError::NotFound),
201+
}
202+
}
203+
None => Err(IdpError::NotFound),
204+
}
205+
}
206+
152207
async fn unix_user_get(
153208
&self,
154209
id: &Id,
@@ -491,6 +546,61 @@ impl IdProvider for HimmelblauProvider {
491546
}
492547
}
493548

549+
async fn unix_user_access(
550+
&self,
551+
id: &Id,
552+
scopes: Vec<String>,
553+
old_token: Option<&UserToken>,
554+
tpm: &mut tpm::BoxedDynTpm,
555+
machine_key: &tpm::MachineKey,
556+
) -> Result<UnixUserToken, IdpError> {
557+
/* Use the prt mem cache to refresh the user token */
558+
let account_id = match old_token {
559+
Some(token) => token.spn.clone(),
560+
None => id.to_string().clone(),
561+
};
562+
let prt = self.refresh_cache.refresh_token(&account_id).await?;
563+
self.client
564+
.write()
565+
.await
566+
.exchange_prt_for_access_token(
567+
&prt,
568+
scopes.iter().map(|s| s.as_ref()).collect(),
569+
None,
570+
tpm,
571+
machine_key,
572+
)
573+
.await
574+
.map_err(|e| {
575+
error!("{:?}", e);
576+
IdpError::BadRequest
577+
})
578+
}
579+
580+
async fn unix_user_prt_cookie(
581+
&self,
582+
id: &Id,
583+
old_token: Option<&UserToken>,
584+
tpm: &mut tpm::BoxedDynTpm,
585+
machine_key: &tpm::MachineKey,
586+
) -> Result<String, IdpError> {
587+
/* Use the prt mem cache to refresh the user token */
588+
let account_id = match old_token {
589+
Some(token) => token.spn.clone(),
590+
None => id.to_string().clone(),
591+
};
592+
let prt = self.refresh_cache.refresh_token(&account_id).await?;
593+
self.client
594+
.write()
595+
.await
596+
.acquire_prt_sso_cookie(&prt, tpm, machine_key)
597+
.await
598+
.map_err(|e| {
599+
error!("Failed to request prt cookie: {:?}", e);
600+
IdpError::BadRequest
601+
})
602+
}
603+
494604
async fn unix_user_get(
495605
&self,
496606
id: &Id,
@@ -555,7 +665,10 @@ impl IdProvider for HimmelblauProvider {
555665
displayname: "".to_string(),
556666
shell: Some(config.get_shell(Some(&self.domain))),
557667
groups,
558-
sshkeys: vec![],
668+
tenant_id: Uuid::parse_str(&self.tenant_id).map_err(|e| {
669+
error!("{:?}", e);
670+
IdpError::BadRequest
671+
})?,
559672
valid: true,
560673
});
561674
} else {
@@ -1344,7 +1457,6 @@ impl HimmelblauProvider {
13441457
groups = vec![];
13451458
}
13461459
};
1347-
let sshkeys: Vec<String> = vec![];
13481460
let valid = true;
13491461
let idmap = self.idmap.read().await;
13501462
let gidnumber = match config.get_id_attr_map() {
@@ -1376,7 +1488,10 @@ impl HimmelblauProvider {
13761488
displayname: value.id_token.name.clone(),
13771489
shell: Some(config.get_shell(Some(&self.domain))),
13781490
groups,
1379-
sshkeys,
1491+
tenant_id: Uuid::parse_str(&self.tenant_id).map_err(|e| {
1492+
error!("{:?}", e);
1493+
IdpError::BadRequest
1494+
})?,
13801495
valid,
13811496
})
13821497
}

0 commit comments

Comments
 (0)