Skip to content

Commit 16ee889

Browse files
abh1sarDaanHooglandlucas-a-martinsLucas Martins
authored andcommitted
Disable API Key Access for users, accounts and domains (apache#9741)
* cli changes to update user/account, list by apikeyaccess, domain level setting * UI changes for updating user/account and searchfilter in listview * make the api parameters and setting accessible only to root admin * revert changes to ui/package-lock.json * minor changes to description strings * UT for ApiServer and AccountManagerImpl classes * fix pre-commit failure * Added a constant for the string System * UT for searchForUsers and searchForAccounts * Fix marvin test error * Update schema to use idempotent add column * Fix `updateTemplatePermission` when the UI is set to a language other than English (apache#9766) * Fix updateTemplatePermission UI in non-english language * Improve fix --------- Co-authored-by: Lucas Martins <[email protected]> * Added user name uuid to logging * Add events when api key access is changed via api or config setting * fix the userid for api key access update event * Fix ut failure after event logging * Convert drop down to radio-button in edit user and account * Add ApiKeyAccess status in User InfoCard for Users if Api key is generated * Return apiKeyAccess in user and account response only for Root Admin * fixed noredist build failure * Show apikeyaccess on the left panel in the user view for root admins as well * don't show divider if apiKeyAccess is not shown to user * Fix events generated to set Username, Account and Domain of the caller correctly * cli changes to update user/account, list by apikeyaccess, domain level setting * UI changes for updating user/account and searchfilter in listview * make the api parameters and setting accessible only to root admin * revert changes to ui/package-lock.json * minor changes to description strings * UT for ApiServer and AccountManagerImpl classes * fix pre-commit failure * Added a constant for the string System * UT for searchForUsers and searchForAccounts * Fix marvin test error * Update schema to use idempotent add column * Added user name uuid to logging * Add events when api key access is changed via api or config setting * fix the userid for api key access update event * Fix ut failure after event logging * Convert drop down to radio-button in edit user and account * Add ApiKeyAccess status in User InfoCard for Users if Api key is generated * Return apiKeyAccess in user and account response only for Root Admin * fixed noredist build failure * Show apikeyaccess on the left panel in the user view for root admins as well * don't show divider if apiKeyAccess is not shown to user * Fix events generated to set Username, Account and Domain of the caller correctly * Added DB upgrade path from 42000 to 42010 --------- Co-authored-by: Daan Hoogland <[email protected]> Co-authored-by: Lucas Martins <[email protected]> Co-authored-by: Lucas Martins <[email protected]>
1 parent c584a13 commit 16ee889

File tree

47 files changed

+894
-62
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+894
-62
lines changed

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ public class EventTypes {
296296

297297
//register for user API and secret keys
298298
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY";
299+
public static final String API_KEY_ACCESS_UPDATE = "API.KEY.ACCESS.UPDATE";
299300

300301
// Template Events
301302
public static final String EVENT_TEMPLATE_CREATE = "TEMPLATE.CREATE";

api/src/main/java/com/cloud/user/Account.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,8 @@ public static Type getFromValue(Integer type){
9393

9494
boolean isDefault();
9595

96+
public void setApiKeyAccess(Boolean apiKeyAccess);
97+
98+
public Boolean getApiKeyAccess();
99+
96100
}

api/src/main/java/com/cloud/user/AccountService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22+
import com.cloud.utils.Pair;
2223
import org.apache.cloudstack.acl.ControlledEntity;
2324
import org.apache.cloudstack.acl.RoleType;
2425
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -127,9 +128,9 @@ User createUser(String userName, String password, String firstName, String lastN
127128
*/
128129
UserAccount getUserAccountById(Long userId);
129130

130-
public Map<String, String> getKeys(GetUserKeysCmd cmd);
131+
public Pair<Boolean, Map<String, String>> getKeys(GetUserKeysCmd cmd);
131132

132-
public Map<String, String> getKeys(Long userId);
133+
public Pair<Boolean, Map<String, String>> getKeys(Long userId);
133134

134135
/**
135136
* Lists user two-factor authentication provider plugins

api/src/main/java/com/cloud/user/User.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,9 @@ public enum Source {
9494
public boolean isUser2faEnabled();
9595

9696
public String getKeyFor2fa();
97+
98+
public void setApiKeyAccess(Boolean apiKeyAccess);
99+
100+
public Boolean getApiKeyAccess();
101+
97102
}

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class ApiConstants {
3535
public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm";
3636
public static final String ANNOTATION = "annotation";
3737
public static final String API_KEY = "apikey";
38+
public static final String API_KEY_ACCESS = "apikeyaccess";
3839
public static final String ARCHIVED = "archived";
3940
public static final String ARCH = "arch";
4041
public static final String AS_NUMBER = "asnumber";
@@ -1346,4 +1347,30 @@ public enum VMDetails {
13461347
public enum DomainDetails {
13471348
all, resource, min;
13481349
}
1350+
1351+
public enum ApiKeyAccess {
1352+
DISABLED(false),
1353+
ENABLED(true),
1354+
INHERIT(null);
1355+
1356+
Boolean apiKeyAccess;
1357+
1358+
ApiKeyAccess(Boolean keyAccess) {
1359+
apiKeyAccess = keyAccess;
1360+
}
1361+
1362+
public Boolean toBoolean() {
1363+
return apiKeyAccess;
1364+
}
1365+
1366+
public static ApiKeyAccess fromBoolean(Boolean value) {
1367+
if (value == null) {
1368+
return INHERIT;
1369+
} else if (value) {
1370+
return ENABLED;
1371+
} else {
1372+
return DISABLED;
1373+
}
1374+
}
1375+
}
13491376
}

api/src/main/java/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121

2222
import javax.inject.Inject;
2323

24+
import org.apache.cloudstack.acl.RoleType;
2425
import org.apache.cloudstack.api.ApiCommandResourceType;
26+
import org.apache.cloudstack.api.command.user.UserCmd;
2527
import org.apache.cloudstack.api.response.RoleResponse;
2628

2729
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -40,8 +42,8 @@
4042
import com.cloud.user.Account;
4143

4244
@APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {Account.class},
43-
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
44-
public class UpdateAccountCmd extends BaseCmd {
45+
responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
46+
public class UpdateAccountCmd extends BaseCmd implements UserCmd {
4547

4648
/////////////////////////////////////////////////////
4749
//////////////// API parameters /////////////////////
@@ -70,6 +72,9 @@ public class UpdateAccountCmd extends BaseCmd {
7072
@Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "Details for the account used to store specific parameters")
7173
private Map details;
7274

75+
@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "Determines if Api key access for this user is enabled, disabled or inherits the value from its parent, the domain level setting api.key.access", since = "4.20.1.0", authorized = {RoleType.Admin})
76+
private String apiKeyAccess;
77+
7378
@Inject
7479
RegionService _regionService;
7580

@@ -109,6 +114,10 @@ public Map getDetails() {
109114
return params;
110115
}
111116

117+
public String getApiKeyAccess() {
118+
return apiKeyAccess;
119+
}
120+
112121
/////////////////////////////////////////////////////
113122
/////////////// API Implementation///////////////////
114123
/////////////////////////////////////////////////////
@@ -131,7 +140,7 @@ public long getEntityOwnerId() {
131140
public void execute() {
132141
Account result = _regionService.updateAccount(this);
133142
if (result != null){
134-
AccountResponse response = _responseGenerator.createAccountResponse(ResponseView.Full, result);
143+
AccountResponse response = _responseGenerator.createAccountResponse(getResponseView(), result);
135144
response.setResponseName(getCommandName());
136145
setResponseObject(response);
137146
} else {

api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserKeysCmd.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.cloud.user.Account;
2222
import com.cloud.user.User;
23+
import com.cloud.utils.Pair;
2324
import org.apache.cloudstack.acl.RoleType;
2425
import org.apache.cloudstack.api.APICommand;
2526
import org.apache.cloudstack.api.ApiConstants;
@@ -54,11 +55,13 @@ public Long getID(){
5455
else return Account.ACCOUNT_ID_SYSTEM;
5556
}
5657
public void execute(){
57-
Map<String, String> keys = _accountService.getKeys(this);
58+
Pair<Boolean, Map<String, String>> keys = _accountService.getKeys(this);
59+
5860
RegisterResponse response = new RegisterResponse();
5961
if(keys != null){
60-
response.setApiKey(keys.get("apikey"));
61-
response.setSecretKey(keys.get("secretkey"));
62+
response.setApiKeyAccess(keys.first());
63+
response.setApiKey(keys.second().get("apikey"));
64+
response.setSecretKey(keys.second().get("secretkey"));
6265
}
6366

6467
response.setObjectName("userkeys");

api/src/main/java/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,23 @@
1919
import com.cloud.server.ResourceIcon;
2020
import com.cloud.server.ResourceTag;
2121
import com.cloud.user.Account;
22+
import org.apache.cloudstack.acl.RoleType;
23+
import org.apache.cloudstack.api.command.user.UserCmd;
2224
import org.apache.cloudstack.api.response.ResourceIconResponse;
2325

2426
import org.apache.cloudstack.api.APICommand;
2527
import org.apache.cloudstack.api.ApiConstants;
2628
import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
2729
import org.apache.cloudstack.api.Parameter;
30+
import org.apache.cloudstack.api.ResponseObject.ResponseView;
2831
import org.apache.cloudstack.api.response.ListResponse;
2932
import org.apache.cloudstack.api.response.UserResponse;
3033

3134
import java.util.List;
3235

3336
@APICommand(name = "listUsers", description = "Lists user accounts", responseObject = UserResponse.class,
34-
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
35-
public class ListUsersCmd extends BaseListAccountResourcesCmd {
37+
responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
38+
public class ListUsersCmd extends BaseListAccountResourcesCmd implements UserCmd {
3639

3740

3841
/////////////////////////////////////////////////////
@@ -53,6 +56,9 @@ public class ListUsersCmd extends BaseListAccountResourcesCmd {
5356
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "List user by the username")
5457
private String username;
5558

59+
@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "List users by the Api key access value", since = "4.20.1.0", authorized = {RoleType.Admin})
60+
private String apiKeyAccess;
61+
5662
@Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN,
5763
description = "flag to display the resource icon for users")
5864
private Boolean showIcon;
@@ -77,6 +83,10 @@ public String getUsername() {
7783
return username;
7884
}
7985

86+
public String getApiKeyAccess() {
87+
return apiKeyAccess;
88+
}
89+
8090
public Boolean getShowIcon() {
8191
return showIcon != null ? showIcon : false;
8292
}
@@ -87,7 +97,7 @@ public Boolean getShowIcon() {
8797

8898
@Override
8999
public void execute() {
90-
ListResponse<UserResponse> response = _queryService.searchForUsers(this);
100+
ListResponse<UserResponse> response = _queryService.searchForUsers(getResponseView(), this);
91101
response.setResponseName(getCommandName());
92102
this.setResponseObject(response);
93103
if (response != null && response.getCount() > 0 && getShowIcon()) {

api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import javax.inject.Inject;
2020

21+
import org.apache.cloudstack.acl.RoleType;
2122
import org.apache.cloudstack.api.APICommand;
2223
import org.apache.cloudstack.api.ApiCommandResourceType;
2324
import org.apache.cloudstack.api.ApiConstants;
@@ -69,6 +70,9 @@ public class UpdateUserCmd extends BaseCmd {
6970
@Parameter(name = ApiConstants.USER_SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey")
7071
private String secretKey;
7172

73+
@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "Determines if Api key access for this user is enabled, disabled or inherits the value from its parent, the owning account", since = "4.20.1.0", authorized = {RoleType.Admin})
74+
private String apiKeyAccess;
75+
7276
@Parameter(name = ApiConstants.TIMEZONE,
7377
type = CommandType.STRING,
7478
description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
@@ -120,6 +124,10 @@ public String getSecretKey() {
120124
return secretKey;
121125
}
122126

127+
public String getApiKeyAccess() {
128+
return apiKeyAccess;
129+
}
130+
123131
public String getTimezone() {
124132
return timezone;
125133
}

api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.EnumSet;
2121
import java.util.List;
2222

23+
import org.apache.cloudstack.acl.RoleType;
2324
import org.apache.cloudstack.api.APICommand;
2425
import org.apache.cloudstack.api.ApiCommandResourceType;
2526
import org.apache.cloudstack.api.ApiConstants;
@@ -70,6 +71,9 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC
7071
description = "comma separated list of account details requested, value can be a list of [ all, resource, min]")
7172
private List<String> viewDetails;
7273

74+
@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "List accounts by the Api key access value", since = "4.20.1.0", authorized = {RoleType.Admin})
75+
private String apiKeyAccess;
76+
7377
@Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN,
7478
description = "flag to display the resource icon for accounts")
7579
private Boolean showIcon;
@@ -120,6 +124,10 @@ public EnumSet<DomainDetails> getDetails() throws InvalidParameterValueException
120124
return dv;
121125
}
122126

127+
public String getApiKeyAccess() {
128+
return apiKeyAccess;
129+
}
130+
123131
public boolean getShowIcon() {
124132
return showIcon != null ? showIcon : false;
125133
}

0 commit comments

Comments
 (0)