1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
use kanidm_client::{KanidmClient, KanidmClientBuilder};

use crate::error::Error;
use crate::profile::Profile;

// This client contains our admin and idm_admin connections that are
// pre-authenticated for use against the kanidm server. In addition,
// new clients can be requested for our test actors.
pub struct KanidmOrcaClient {
    #[allow(dead_code)]
    admin_client: KanidmClient,
    idm_admin_client: KanidmClient,
    // In future we probably need a way to connect to all the nodes?
    // Or we just need all their uris.
}

impl KanidmOrcaClient {
    pub async fn new(profile: &Profile) -> Result<Self, Error> {
        let admin_client = KanidmClientBuilder::new()
            .address(profile.control_uri().to_string())
            .danger_accept_invalid_hostnames(true)
            .danger_accept_invalid_certs(true)
            .request_timeout(1200)
            .build()
            .map_err(|err| {
                error!(?err, "Unable to create kanidm client");
                Error::KanidmClient
            })?;

        admin_client
            .auth_simple_password("admin", profile.admin_password())
            .await
            .map_err(|err| {
                error!(?err, "Unable to authenticate as admin");
                Error::KanidmClient
            })?;

        let idm_admin_client = admin_client.new_session().map_err(|err| {
            error!(?err, "Unable to create new session");
            Error::KanidmClient
        })?;

        idm_admin_client
            .auth_simple_password("idm_admin", profile.idm_admin_password())
            .await
            .map_err(|err| {
                error!(?err, "Unable to authenticate as idm_admin");
                Error::KanidmClient
            })?;

        Ok(KanidmOrcaClient {
            admin_client,
            idm_admin_client,
        })
    }

    pub async fn disable_mfa_requirement(&self) -> Result<(), Error> {
        self.idm_admin_client
            .group_account_policy_credential_type_minimum_set("idm_all_persons", "any")
            .await
            .map_err(|err| {
                error!(?err, "Unable to modify idm_all_persons policy");
                Error::KanidmClient
            })
    }

    pub async fn extend_privilege_expiry(&self) -> Result<(), Error> {
        self.idm_admin_client
            .group_account_policy_privilege_expiry_set("idm_all_persons", 3600)
            .await
            .map_err(|err| {
                error!(?err, "Unable to modify idm_all_persons policy");
                Error::KanidmClient
            })?;

        self.idm_admin_client
            .group_account_policy_privilege_expiry_set("idm_all_accounts", 3600)
            .await
            .map_err(|err| {
                error!(?err, "Unable to modify idm_all_accounts policy");
                Error::KanidmClient
            })
    }

    pub async fn person_exists(&self, username: &str) -> Result<bool, Error> {
        self.idm_admin_client
            .idm_person_account_get(username)
            .await
            .map(|e| e.is_some())
            .map_err(|err| {
                error!(?err, ?username, "Unable to check person");
                Error::KanidmClient
            })
    }

    pub async fn person_create(&self, username: &str, display_name: &str) -> Result<(), Error> {
        self.idm_admin_client
            .idm_person_account_create(username, display_name)
            .await
            .map_err(|err| {
                error!(?err, ?username, "Unable to create person");
                Error::KanidmClient
            })
    }

    pub async fn person_set_primary_password_only(
        &self,
        username: &str,
        password: &str,
    ) -> Result<(), Error> {
        self.idm_admin_client
            .idm_person_account_primary_credential_set_password(username, password)
            .await
            .map_err(|err| {
                error!(?err, ?username, "Unable to set person password");
                Error::KanidmClient
            })
    }

    pub async fn group_set_members(&self, group_name: &str, members: &[&str]) -> Result<(), Error> {
        self.idm_admin_client
            .idm_group_set_members(group_name, members)
            .await
            .map_err(|err| {
                error!(?err, ?group_name, "Unable to set group members");
                Error::KanidmClient
            })
    }

    pub async fn group_add_members(&self, group_name: &str, members: &[&str]) -> Result<(), Error> {
        self.idm_admin_client
            .idm_group_add_members(group_name, members)
            .await
            .map_err(|err| {
                error!(?err, ?group_name, "Unable to add group members");
                Error::KanidmClient
            })
    }

    pub async fn group_exists(&self, group_name: &str) -> Result<bool, Error> {
        self.idm_admin_client
            .idm_group_get(group_name)
            .await
            .map(|e| e.is_some())
            .map_err(|err| {
                error!(?err, ?group_name, "Unable to check group");
                Error::KanidmClient
            })
    }

    pub async fn group_create(&self, group_name: &str) -> Result<(), Error> {
        self.idm_admin_client
            .idm_group_create(group_name, Some("idm_admins"))
            .await
            .map_err(|err| {
                error!(?err, ?group_name, "Unable to create group");
                Error::KanidmClient
            })
    }
}