diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql b/engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql index 3365f1f855ba..14e9f04bf3dc 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql @@ -239,3 +239,25 @@ CREATE TABLE IF NOT EXISTS `cloud`.`instance_boot_group_details` ( PRIMARY KEY (`id`), CONSTRAINT `fk_instance_boot_group_details__group_id` FOREIGN KEY (`boot_group_id`) REFERENCES `instance_boot_group` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- @APICommand(authorized=...) alone doesn't grant access under dynamic RBAC (the default). +-- Backfill the LDAP account APIs for any role that can already create accounts natively. +INSERT INTO cloud.role_permissions (uuid, role_id, rule, permission, sort_order) +SELECT uuid(), role_id, 'listLdapUsers', permission, sort_order +FROM cloud.role_permissions rp +WHERE rule = 'createAccount' AND NOT EXISTS(SELECT 1 FROM cloud.role_permissions rp_ WHERE rp.role_id = rp_.role_id AND rp_.rule = 'listLdapUsers'); + +INSERT INTO cloud.role_permissions (uuid, role_id, rule, permission, sort_order) +SELECT uuid(), role_id, 'ldapCreateAccount', permission, sort_order +FROM cloud.role_permissions rp +WHERE rule = 'createAccount' AND NOT EXISTS(SELECT 1 FROM cloud.role_permissions rp_ WHERE rp.role_id = rp_.role_id AND rp_.rule = 'ldapCreateAccount'); + +INSERT INTO cloud.role_permissions (uuid, role_id, rule, permission, sort_order) +SELECT uuid(), role_id, 'linkAccountToLdap', permission, sort_order +FROM cloud.role_permissions rp +WHERE rule = 'createAccount' AND NOT EXISTS(SELECT 1 FROM cloud.role_permissions rp_ WHERE rp.role_id = rp_.role_id AND rp_.rule = 'linkAccountToLdap'); + +INSERT INTO cloud.role_permissions (uuid, role_id, rule, permission, sort_order) +SELECT uuid(), role_id, 'importLdapUsers', permission, sort_order +FROM cloud.role_permissions rp +WHERE rule = 'createAccount' AND NOT EXISTS(SELECT 1 FROM cloud.role_permissions rp_ WHERE rp.role_id = rp_.role_id AND rp_.rule = 'importLdapUsers'); diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java index 3aa3e0502268..8835c9fe4b0b 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java @@ -44,7 +44,8 @@ import java.security.SecureRandom; import java.util.Map; -@APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.DomainAdmin}) public class LdapCreateAccountCmd extends BaseCmd { private static final String s_name = "createaccountresponse"; diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java index d6df27ccfcb9..f497e49d6a01 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapImportUsersCmd.java @@ -56,7 +56,8 @@ import com.cloud.user.UserAccount; import com.cloud.utils.StringUtils; -@APICommand(name = "importLdapUsers", description = "Import LDAP users", responseObject = LdapUserResponse.class, since = "4.3.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "importLdapUsers", description = "Import LDAP users", responseObject = LdapUserResponse.class, since = "4.3.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.DomainAdmin}) public class LdapImportUsersCmd extends BaseListCmd { diff --git a/ui/src/store/modules/user.js b/ui/src/store/modules/user.js index 4103ff920d63..d3835afea94a 100644 --- a/ui/src/store/modules/user.js +++ b/ui/src/store/modules/user.js @@ -451,6 +451,9 @@ const user = { commit('SET_NAME', result.firstname + ' ' + result.lastname) commit('SET_AVATAR', result.icon?.base64image || '') store.dispatch('SetCsLatestVersion', result.rolename) + store.dispatch('UpdateConfiguration').catch(error => { + reject(error) + }) }).catch(error => { reject(error) }) @@ -464,13 +467,6 @@ const user = { }).catch(ignored => { }) - getAPI('listLdapConfigurations').then(response => { - const ldapEnable = (response.ldapconfigurationresponse.count > 0) - commit('SET_LDAP', ldapEnable) - }).catch(error => { - reject(error) - }) - getAPI('cloudianIsEnabled').then(response => { const cloudian = response.cloudianisenabledresponse.cloudianisenabled || {} commit('SET_CLOUDIAN', cloudian) @@ -601,13 +597,15 @@ const user = { }) }, UpdateConfiguration ({ commit }) { - return new Promise((resolve, reject) => { - getAPI('listLdapConfigurations').then(response => { - const ldapEnable = (response.ldapconfigurationresponse.count > 0) - commit('SET_LDAP', ldapEnable) - }).catch(error => { - reject(error) - }) + // Root admins see LDAP as enabled if any configuration exists; everyone else + // only when a global configuration or one linked to their own domain exists + const userInfo = store.getters.userInfo + const queries = userInfo.roletype === 'Admin' + ? [{ listall: true }] + : [{}, { domainid: userInfo.domainid }] + return Promise.all(queries.map(params => getAPI('listLdapConfigurations', params))).then(responses => { + const ldapEnable = responses.some(response => response.ldapconfigurationresponse.count > 0) + commit('SET_LDAP', ldapEnable) }) }, SetDomainStore ({ commit }, domainStore) {