Skip to content

Commit 4817b13

Browse files
author
klaus.freitas.scclouds
committed
fixing asterisk, refactoring apikey permissions check
1 parent 03632d5 commit 4817b13

File tree

32 files changed

+570
-348
lines changed

32 files changed

+570
-348
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323
import org.apache.cloudstack.acl.RoleType;
2424
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
2525
import org.apache.cloudstack.acl.apikeypair.ApiKeyPair;
26+
import org.apache.cloudstack.acl.apikeypair.ApiKeyPairPermission;
27+
import org.apache.cloudstack.api.BaseCmd;
2628
import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd;
29+
import org.apache.cloudstack.api.command.admin.user.DeleteUserKeysCmd;
2730
import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
31+
import org.apache.cloudstack.api.command.admin.user.ListUserKeyRulesCmd;
2832
import org.apache.cloudstack.api.command.admin.user.ListUserKeysCmd;
2933
import org.apache.cloudstack.api.command.admin.user.RegisterUserKeysCmd;
3034
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
@@ -120,6 +124,8 @@ User createUser(String userName, String password, String firstName, String lastN
120124

121125
void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException;
122126

127+
void validateCallingUserHasAccessToDesiredUser(Long userId);
128+
123129
Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly);
124130

125131
/**
@@ -133,6 +139,11 @@ User createUser(String userName, String password, String firstName, String lastN
133139

134140
ListResponse<ApiKeyPairResponse> getKeys(ListUserKeysCmd cmd);
135141

142+
List<ApiKeyPairPermission> listKeyRules(ListUserKeyRulesCmd cmd);
143+
144+
void deleteApiKey(DeleteUserKeysCmd cmd);
145+
146+
void deleteApiKey(ApiKeyPair id);
136147
/**
137148
* Lists user two-factor authentication provider plugins
138149
* @return list of providers
@@ -150,4 +161,7 @@ User createUser(String userName, String password, String firstName, String lastN
150161

151162
ApiKeyPair getKeyPairById(Long id);
152163

164+
ApiKeyPair getKeyPairByApiKey(String apiKey);
165+
166+
String getAccessingApiKey (BaseCmd cmd);
153167
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.user;
18+
19+
public enum ApiKeyPairState {
20+
ENABLED, REMOVED, EXPIRED
21+
}

api/src/main/java/org/apache/cloudstack/acl/RoleService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,24 @@ public interface RoleService {
101101

102102
Permission getRolePermission(String permission);
103103

104+
List<RolePermissionEntity> findAllRolePermissionsEntityBy(Long roleId);
105+
104106
int removeRolesIfNeeded(List<? extends Role> roles);
107+
108+
/**
109+
* Checks if the role of the caller account has compatible permissions of the specified role permissions.
110+
* For each permission of the roleToAccess, the role of the caller needs to contain the same permission.
111+
*
112+
* @param rolePermissions the permissions of the caller role.
113+
* @param rolePermissionsToAccess the permissions for the role that the caller role wants to access.
114+
* @return True if the role can be accessed with the given permissions; false otherwise.
115+
*/
116+
boolean roleHasPermission(Map<String, Permission> rolePermissions, List<RolePermissionEntity> rolePermissionsToAccess);
117+
118+
/**
119+
* Given a list of role permissions, returns a {@link Map} containing the API name as the key and the {@link Permission} for the API as the value.
120+
*
121+
* @param rolePermissions Permissions for the role from role.
122+
*/
123+
Map<String, Permission> getRoleRulesAndPermissions(List<RolePermissionEntity> rolePermissions);
105124
}

api/src/main/java/org/apache/cloudstack/acl/Rule.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,18 @@
2525

2626
public final class Rule {
2727
private final String rule;
28+
private final Pattern matchingPattern;
2829
private final static Pattern ALLOWED_PATTERN = Pattern.compile("^[a-zA-Z0-9*]+$");
2930

3031
public Rule(final String rule) {
3132
validate(rule);
3233
this.rule = rule;
34+
matchingPattern = Pattern.compile(rule.toLowerCase().replace("*", "(\\w*\\*?)+"));
3335
}
3436

3537
public boolean matches(final String commandName) {
36-
return StringUtils.isNotEmpty(commandName)
37-
&& commandName.toLowerCase().matches(rule.toLowerCase().replace("*", "\\w*"));
38+
return StringUtils.isNotEmpty(commandName) &&
39+
matchingPattern.matcher(commandName.toLowerCase()).matches();
3840
}
3941

4042
public String getRuleString() {

api/src/main/java/org/apache/cloudstack/acl/apikeypair/ApiKeyPair.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,7 @@ public interface ApiKeyPair extends ControlledEntity, InternalIdentity, Identity
3232
String getSecretKey();
3333
String getName();
3434
Date getRemoved();
35-
boolean validateDate(boolean throwException);
35+
void setRemoved(Date date);
36+
void validateDate();
37+
boolean hasEndDatePassed();
3638
}

api/src/main/java/org/apache/cloudstack/acl/apikeypair/ApiKeyPairService.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@
1919
import java.util.List;
2020

2121
public interface ApiKeyPairService {
22-
List<ApiKeyPairPermission> findAllPermissionsByKeyPairId(Long apiKeyPairId);
22+
List<ApiKeyPairPermission> findAllPermissionsByKeyPairId(Long apiKeyPairId, Long roleId);
2323

2424
ApiKeyPair findByApiKey(String apiKey);
2525

2626
ApiKeyPair findById(Long id);
2727

28-
void deleteApiKey(ApiKeyPair id);
29-
3028
void validateCallingUserHasAccessToDesiredUser(Long userId);
3129
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
public class ApiConstants {
2020
public static final String ACCOUNT = "account";
2121
public static final String ACCOUNTS = "accounts";
22+
public static final String ACCOUNT_NAME = "accountname";
2223
public static final String ACCOUNT_TYPE = "accounttype";
2324
public static final String ACCOUNT_ID = "accountid";
2425
public static final String ACCOUNT_IDS = "accountids";
@@ -35,6 +36,8 @@ public class ApiConstants {
3536
public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm";
3637
public static final String ANNOTATION = "annotation";
3738
public static final String API_KEY = "apikey";
39+
public static final String API_KEY_FILTER = "apikeyfilter";
40+
public static final String HEADER_API_KEY = "apiKey";
3841
public static final String ARCHIVED = "archived";
3942
public static final String ARCH = "arch";
4043
public static final String AS_NUMBER = "asnumber";
@@ -446,6 +449,7 @@ public class ApiConstants {
446449
public static final String SHOW_RESOURCE_ICON = "showicon";
447450
public static final String SHOW_INACTIVE = "showinactive";
448451
public static final String SHOW_UNIQUE = "showunique";
452+
public static final String SHOW_PERMISSIONS = "showpermissions";
449453
public static final String SIGNATURE = "signature";
450454
public static final String SIGNATURE_VERSION = "signatureversion";
451455
public static final String SINCE = "since";
@@ -640,6 +644,7 @@ public class ApiConstants {
640644
public static final String ROLE_TYPE = "roletype";
641645
public static final String ROLE_NAME = "rolename";
642646
public static final String PERMISSION = "permission";
647+
public static final String PERMISSIONS = "permissions";
643648
public static final String RULE = "rule";
644649
public static final String RULES = "rules";
645650
public static final String RULE_ID = "ruleid";

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.cloudstack.api.command.admin.user;
1818

1919
import com.cloud.event.EventTypes;
20-
import com.cloud.exception.InvalidParameterValueException;
2120
import com.cloud.user.Account;
2221
import org.apache.cloudstack.acl.apikeypair.ApiKeyPair;
2322
import org.apache.cloudstack.api.ACL;
@@ -51,20 +50,13 @@ public long getEntityOwnerId() {
5150
return Account.ACCOUNT_ID_SYSTEM;
5251
}
5352

54-
private Long getId() {
53+
public Long getId() {
5554
return id;
5655
}
5756

5857
@Override
5958
public void execute() {
60-
ApiKeyPair keyPair = apiKeyPairService.findById(getId());
61-
if (keyPair == null) {
62-
throw new InvalidParameterValueException(String.format("No keypair found with the id [%s].", getId()));
63-
}
64-
apiKeyPairService.validateCallingUserHasAccessToDesiredUser(keyPair.getUserId());
65-
66-
apiKeyPairService.deleteApiKey(keyPair);
67-
59+
_accountService.deleteApiKey(this);
6860
SuccessResponse response = new SuccessResponse(getCommandName());
6961
this.setResponseObject(response);
7062
}

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

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020

2121
import com.cloud.exception.InsufficientCapacityException;
22-
import com.cloud.exception.InvalidParameterValueException;
2322
import com.cloud.exception.ResourceUnavailableException;
2423
import com.cloud.user.Account;
2524
import java.util.List;
@@ -28,7 +27,7 @@
2827
import org.apache.cloudstack.api.ACL;
2928
import org.apache.cloudstack.api.APICommand;
3029
import org.apache.cloudstack.api.ApiConstants;
31-
import org.apache.cloudstack.api.BaseCmd;
30+
import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
3231
import org.apache.cloudstack.api.Parameter;
3332
import org.apache.cloudstack.api.ServerApiException;
3433
import org.apache.cloudstack.api.response.ApiKeyPairResponse;
@@ -42,10 +41,10 @@
4241
responseHasSensitiveInfo = false,
4342
since = "4.20.0")
4443

45-
public class ListUserKeyRulesCmd extends BaseCmd {
44+
public class ListUserKeyRulesCmd extends BaseListDomainResourcesCmd {
4645

4746
@ACL
48-
@Parameter(name=ApiConstants.ID, type = CommandType.UUID, entityType = ApiKeyPairResponse.class, description = "ID of the keypair.", required = true)
47+
@Parameter(name = ApiConstants.KEYPAIR_ID, type = CommandType.UUID, entityType = ApiKeyPairResponse.class, description = "ID of the keypair.", required = true)
4948
private Long id;
5049

5150
public Long getId() {
@@ -62,13 +61,7 @@ public long getEntityOwnerId() {
6261

6362
@Override
6463
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException {
65-
ApiKeyPair keyPair = apiKeyPairService.findById(getId());
66-
if (keyPair == null) {
67-
throw new InvalidParameterValueException(String.format("No keypair found with the id [%s].", getId()));
68-
}
69-
apiKeyPairService.validateCallingUserHasAccessToDesiredUser(keyPair.getUserId());
70-
71-
List<ApiKeyPairPermission> permissions = apiKeyPairService.findAllPermissionsByKeyPairId(keyPair.getId());
64+
List<ApiKeyPairPermission> permissions = _accountService.listKeyRules(this);
7265
ListResponse<BaseRolePermissionResponse> response = _responseGenerator.createKeypairPermissionsResponse(permissions);
7366
response.setResponseName(getCommandName());
7467
setResponseObject(response);

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,21 @@
4545
public class ListUserKeysCmd extends BaseListDomainResourcesCmd {
4646

4747
@ACL
48-
@Parameter(name=ApiConstants.ID, type = CommandType.UUID, entityType = UserResponse.class, description = "ID of the user that owns the keys.")
48+
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = UserResponse.class, description = "ID of the user that owns the keys.")
4949
private Long userId;
5050

5151
@ACL
52-
@Parameter(name=ApiConstants.KEYPAIR_ID, type = CommandType.UUID, entityType = ApiKeyPairResponse.class, description = "ID of the keypair.")
52+
@Parameter(name = ApiConstants.KEYPAIR_ID, type = CommandType.UUID, entityType = ApiKeyPairResponse.class, description = "ID of the keypair.")
5353
private Long keyPairId;
5454

55+
@ACL
56+
@Parameter(name = ApiConstants.API_KEY_FILTER, type = CommandType.STRING, description = "API Key of the keypair.")
57+
private String apiKeyFilter;
58+
59+
@Parameter(name = ApiConstants.SHOW_PERMISSIONS, type = CommandType.BOOLEAN, description = "Whether API Key rules should be returned.")
60+
private Boolean showPermissions;
61+
62+
5563
protected Logger logger = LogManager.getLogger(getClass());
5664

5765
public Long getUserId() {
@@ -62,6 +70,14 @@ public Long getKeyId() {
6270
return keyPairId;
6371
}
6472

73+
public String getApiKeyFilter() {
74+
return apiKeyFilter;
75+
}
76+
77+
public Boolean getShowPermissions() {
78+
return showPermissions;
79+
}
80+
6581
public long getEntityOwnerId() {
6682
if (getKeyId() != null) {
6783
ApiKeyPair keypair = apiKeyPairService.findById(getKeyId());

0 commit comments

Comments
 (0)