Skip to content

Commit 170b6ce

Browse files
authored
CLOUDSTACK-10236: Enable dynamic roles for missing props file (#2426)
Automate dynamic roles migration for missing props file - In case commands.properties file is missing, enables dynamic roles. - Adds a new -D or --default flag to migrate-dynamicroles.py script to simply update the global setting and use the default role-rule permissions. - Add warning message, ask admins to move to dynamic roles during upgrade Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent 61a5a29 commit 170b6ce

3 files changed

Lines changed: 37 additions & 9 deletions

File tree

engine/schema/src/com/cloud/upgrade/dao/Upgrade41000to41100.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.apache.log4j.Logger;
3232

3333
import com.cloud.hypervisor.Hypervisor;
34+
import com.cloud.utils.PropertiesUtil;
3435
import com.cloud.utils.exception.CloudRuntimeException;
3536

3637
public class Upgrade41000to41100 implements DbUpgrade {
@@ -65,10 +66,27 @@ public InputStream[] getPrepareScripts() {
6566

6667
@Override
6768
public void performDataMigration(Connection conn) {
69+
checkAndEnableDynamicRoles(conn);
6870
validateUserDataInBase64(conn);
6971
updateSystemVmTemplates(conn);
7072
}
7173

74+
private void checkAndEnableDynamicRoles(final Connection conn) {
75+
final Map<String, String> apiMap = PropertiesUtil.processConfigFile(new String[] { "commands.properties" });
76+
if (apiMap == null || apiMap.isEmpty()) {
77+
if (LOG.isDebugEnabled()) {
78+
LOG.debug("No commands.properties file was found, enabling dynamic roles by setting dynamic.apichecker.enabled to true if not already enabled.");
79+
}
80+
try (final PreparedStatement updateStatement = conn.prepareStatement("INSERT INTO cloud.configuration (category, instance, name, default_value, value) VALUES ('Advanced', 'DEFAULT', 'dynamic.apichecker.enabled', 'false', 'true') ON DUPLICATE KEY UPDATE value='true'")) {
81+
updateStatement.executeUpdate();
82+
} catch (SQLException e) {
83+
LOG.error("Failed to set dynamic.apichecker.enabled to true, please run migrate-dynamicroles.py script to manually migrate to dynamic roles.", e);
84+
}
85+
} else {
86+
LOG.warn("Old commands.properties static checker is deprecated, please use migrate-dynamicroles.py to migrate to dynamic roles. Refer http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/accounts.html#using-dynamic-roles");
87+
}
88+
}
89+
7290
private void validateUserDataInBase64(Connection conn) {
7391
try (final PreparedStatement selectStatement = conn.prepareStatement("SELECT `id`, `user_data` FROM `cloud`.`user_vm` WHERE `user_data` IS NOT NULL;");
7492
final ResultSet selectResultSet = selectStatement.executeQuery()) {

plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
// This is the default API access checker that grab's the user's account
4141
// based on the account type, access is granted
42+
@Deprecated
4243
public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIChecker {
4344

4445
protected static final Logger LOGGER = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class);

scripts/util/migrate-dynamicroles.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ def migrateApiRolePermissions(apis, conn):
5555
if (octetKey[role] & int(apis[api])) > 0:
5656
runSql(conn, "INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), %d, '%s', 'ALLOW', %d);" % (role, api, sortOrder))
5757
sortOrder += 1
58+
print("Static role permissions from commands.properties have been migrated into the db")
59+
60+
61+
def enableDynamicApiChecker(conn):
62+
runSql(conn, "UPDATE `cloud`.`configuration` SET value='true' where name='dynamic.apichecker.enabled'")
63+
conn.commit()
64+
conn.close()
65+
print("Dynamic role based API checker has been enabled!")
5866

5967

6068
def main():
@@ -71,6 +79,8 @@ def main():
7179
help="Host or IP of the MySQL server")
7280
parser.add_option("-f", "--properties-file", action="store", type="string", dest="commandsfile", default="/etc/cloudstack/management/commands.properties",
7381
help="The commands.properties file")
82+
parser.add_option("-D", "--default", action="store_true", dest="defaultRules", default=False,
83+
help="")
7484
parser.add_option("-d", "--dryrun", action="store_true", dest="dryrun", default=False,
7585
help="Dry run and debug operations this tool will perform")
7686
(options, args) = parser.parse_args()
@@ -89,8 +99,14 @@ def main():
8999
port=int(options.port),
90100
db=options.db)
91101

102+
if options.defaultRules:
103+
print("Applying the default role permissions, ignoring any provided properties files(s).")
104+
enableDynamicApiChecker(conn)
105+
sys.exit(0)
106+
92107
if not os.path.isfile(options.commandsfile):
93-
print("Provided commands.properties cannot be accessed or does not exist, please check check permissions")
108+
print("Provided commands.properties cannot be accessed or does not exist.")
109+
print("Please check passed options, or run only with --default option to use the default role permissions.")
94110
sys.exit(1)
95111

96112
while True:
@@ -122,15 +138,8 @@ def main():
122138

123139
# Migrate rules from commands.properties to cloud.role_permissions
124140
migrateApiRolePermissions(apiMap, conn)
125-
print("Static role permissions from commands.properties have been migrated into the db")
126-
127-
# Enable dynamic role based API checker
128-
runSql(conn, "UPDATE `cloud`.`configuration` SET value='true' where name='dynamic.apichecker.enabled'")
129-
conn.commit()
130-
conn.close()
131-
132-
print("Dynamic role based API checker has been enabled!")
133141

142+
enableDynamicApiChecker(conn)
134143

135144
if __name__ == '__main__':
136145
main()

0 commit comments

Comments
 (0)