16
16
// under the License.
17
17
package org .apache .cloudstack .acl ;
18
18
19
+ import java .util .ArrayList ;
19
20
import java .util .HashMap ;
20
21
import java .util .HashSet ;
21
22
import java .util .List ;
@@ -48,7 +49,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API
48
49
private List <PluggableService > services ;
49
50
private Map <RoleType , Set <String >> annotationRoleBasedApisMap = new HashMap <RoleType , Set <String >>();
50
51
51
- private static final Logger logger = Logger .getLogger (DynamicRoleBasedAPIAccessChecker .class .getName ());
52
+ private static final Logger LOGGER = Logger .getLogger (DynamicRoleBasedAPIAccessChecker .class .getName ());
52
53
53
54
protected DynamicRoleBasedAPIAccessChecker () {
54
55
super ();
@@ -57,22 +58,58 @@ protected DynamicRoleBasedAPIAccessChecker() {
57
58
}
58
59
}
59
60
60
- private void denyApiAccess (final String commandName ) throws PermissionDeniedException {
61
- throw new PermissionDeniedException ("The API " + commandName + " is denied for the account's role." );
61
+ @ Override
62
+ public List <String > getApisAllowedToUser (Role role , User user , List <String > apiNames ) throws PermissionDeniedException {
63
+ if (!isEnabled ()) {
64
+ return apiNames ;
65
+ }
66
+
67
+ List <RolePermission > allPermissions = roleService .findAllPermissionsBy (role .getId ());
68
+ List <String > allowedApis = new ArrayList <>();
69
+ for (String api : apiNames ) {
70
+ if (checkApiPermissionByRole (role , api , allPermissions )) {
71
+ allowedApis .add (api );
72
+ }
73
+ }
74
+ return allowedApis ;
62
75
}
63
76
64
- public boolean isDisabled () {
65
- return !roleService .isEnabled ();
77
+ /**
78
+ * Checks if the given Role of an Account has the allowed permission for the given API.
79
+ *
80
+ * @param role to be used on the verification
81
+ * @param apiName to be verified
82
+ * @param allPermissions list of role permissions for the given role
83
+ * @return if the role has the permission for the API
84
+ */
85
+ public boolean checkApiPermissionByRole (Role role , String apiName , List <RolePermission > allPermissions ) {
86
+ for (final RolePermission permission : allPermissions ) {
87
+ if (!permission .getRule ().matches (apiName )) {
88
+ continue ;
89
+ }
90
+
91
+ if (!Permission .ALLOW .equals (permission .getPermission ())) {
92
+ return false ;
93
+ }
94
+
95
+ if (LOGGER .isTraceEnabled ()) {
96
+ LOGGER .trace (String .format ("The API [%s] is allowed for the role %s by the permission [%s]." , apiName , role , permission .getRule ().toString ()));
97
+ }
98
+ return true ;
99
+ }
100
+ return annotationRoleBasedApisMap .get (role .getRoleType ()) != null &&
101
+ annotationRoleBasedApisMap .get (role .getRoleType ()).contains (apiName );
66
102
}
67
103
68
104
@ Override
69
105
public boolean checkAccess (User user , String commandName ) throws PermissionDeniedException {
70
- if (isDisabled ()) {
106
+ if (! isEnabled ()) {
71
107
return true ;
72
108
}
109
+
73
110
Account account = accountService .getAccount (user .getAccountId ());
74
111
if (account == null ) {
75
- throw new PermissionDeniedException ("The account id=" + user . getAccountId () + " for user id=" + user .getId () + "is null" );
112
+ throw new PermissionDeniedException (String . format ( "The account id [%s] for user id [%s] is null." , user .getAccountId (), user . getUuid ()) );
76
113
}
77
114
78
115
return checkAccess (account , commandName );
@@ -81,37 +118,32 @@ public boolean checkAccess(User user, String commandName) throws PermissionDenie
81
118
public boolean checkAccess (Account account , String commandName ) {
82
119
final Role accountRole = roleService .findRole (account .getRoleId ());
83
120
if (accountRole == null || accountRole .getId () < 1L ) {
84
- denyApiAccess ( commandName );
121
+ throw new PermissionDeniedException ( String . format ( "The account [%s] has role null or unknown." , account ) );
85
122
}
86
123
87
- // Allow all APIs for root admins
88
124
if (accountRole .getRoleType () == RoleType .Admin && accountRole .getId () == RoleType .Admin .getId ()) {
125
+ LOGGER .info (String .format ("Account [%s] is Root Admin or Domain Admin, all APIs are allowed." , account ));
89
126
return true ;
90
127
}
91
128
92
- // Check against current list of permissions
93
- for (final RolePermission permission : roleService .findAllPermissionsBy (accountRole .getId ())) {
94
- if (permission .getRule ().matches (commandName )) {
95
- if (Permission .ALLOW .equals (permission .getPermission ())) {
96
- return true ;
97
- } else {
98
- denyApiAccess (commandName );
99
- }
100
- }
101
- }
102
-
103
- // Check annotations
104
- if (annotationRoleBasedApisMap .get (accountRole .getRoleType ()) != null
105
- && annotationRoleBasedApisMap .get (accountRole .getRoleType ()).contains (commandName )) {
129
+ List <RolePermission > allPermissions = roleService .findAllPermissionsBy (accountRole .getId ());
130
+ if (checkApiPermissionByRole (accountRole , commandName , allPermissions )) {
106
131
return true ;
107
132
}
108
-
109
- // Default deny all
110
- throw new UnavailableCommandException ("The API " + commandName + " does not exist or is not available for this account." );
133
+ throw new UnavailableCommandException (String .format ("The API [%s] does not exist or is not available for the account %s." , commandName , account ));
111
134
}
112
135
136
+ /**
137
+ * Only one strategy should be used between StaticRoleBasedAPIAccessChecker and DynamicRoleBasedAPIAccessChecker
138
+ * Default behavior is to use the Dynamic version. The StaticRoleBasedAPIAccessChecker is the legacy version.
139
+ * If roleService is enabled, then it uses the DynamicRoleBasedAPIAccessChecker, otherwise, it will use the
140
+ * StaticRoleBasedAPIAccessChecker.
141
+ */
113
142
@ Override
114
143
public boolean isEnabled () {
144
+ if (!roleService .isEnabled ()) {
145
+ LOGGER .trace ("RoleService is disabled. We will not use DynamicRoleBasedAPIAccessChecker." );
146
+ }
115
147
return roleService .isEnabled ();
116
148
}
117
149
0 commit comments