Validate index and cluster privilege names when creating a role (#46361) (#47063)

This commit adds validation so a role cannot be created with
invalid index or cluster privilege name.

Closes #29703
This commit is contained in:
Yogesh Gaikwad 2019-09-25 18:57:11 +10:00 committed by GitHub
parent 056ac32738
commit 6f453aa6b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 6 deletions

View File

@ -14,10 +14,13 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege;
import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilegeResolver;
import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivilege;
import org.elasticsearch.xpack.core.security.authz.privilege.ConfigurableClusterPrivileges;
import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege;
import org.elasticsearch.xpack.core.security.support.MetadataUtils;
import java.io.IOException;
@ -70,6 +73,24 @@ public class PutRoleRequest extends ActionRequest implements WriteRequest<PutRol
if (name == null) {
validationException = addValidationError("role name is missing", validationException);
}
if (clusterPrivileges != null) {
for (String cp : clusterPrivileges) {
try {
ClusterPrivilegeResolver.resolve(cp);
} catch (IllegalArgumentException ile) {
validationException = addValidationError(ile.getMessage(), validationException);
}
}
}
if (indicesPrivileges != null) {
for (RoleDescriptor.IndicesPrivileges idp : indicesPrivileges) {
try {
IndexPrivilege.get(Sets.newHashSet(idp.getPrivileges()));
} catch (IllegalArgumentException ile) {
validationException = addValidationError(ile.getMessage(), validationException);
}
}
}
if(applicationPrivileges != null) {
for (RoleDescriptor.ApplicationResourcePrivileges privilege : applicationPrivileges) {
try {

View File

@ -8,6 +8,8 @@
package org.elasticsearch.xpack.core.security.authz.privilege;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesAction;
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotAction;
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsAction;
@ -37,6 +39,8 @@ import java.util.stream.Stream;
* Translates cluster privilege names into concrete implementations
*/
public class ClusterPrivilegeResolver {
private static final Logger logger = LogManager.getLogger(ClusterPrivilegeResolver.class);
// shared automatons
private static final Set<String> ALL_SECURITY_PATTERN = Collections.singleton("cluster:admin/xpack/security/*");
private static final Set<String> MANAGE_SAML_PATTERN = Collections.unmodifiableSet(
@ -168,10 +172,12 @@ public class ClusterPrivilegeResolver {
if (fixedPrivilege != null) {
return fixedPrivilege;
}
throw new IllegalArgumentException("unknown cluster privilege [" + name + "]. a privilege must be either " +
String errorMessage = "unknown cluster privilege [" + name + "]. a privilege must be either " +
"one of the predefined cluster privilege names [" +
Strings.collectionToCommaDelimitedString(VALUES.keySet()) + "] or a pattern over one of the available " +
"cluster actions");
"cluster actions";
logger.debug(errorMessage);
throw new IllegalArgumentException(errorMessage);
}

View File

@ -5,6 +5,8 @@
*/
package org.elasticsearch.xpack.core.security.authz.privilege;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.util.automaton.Automaton;
import org.elasticsearch.action.admin.cluster.shards.ClusterSearchShardsAction;
import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistAction;
@ -41,6 +43,7 @@ import static org.elasticsearch.xpack.core.security.support.Automatons.patterns;
import static org.elasticsearch.xpack.core.security.support.Automatons.unionAndMinimize;
public final class IndexPrivilege extends Privilege {
private static final Logger logger = LogManager.getLogger(IndexPrivilege.class);
private static final Automaton ALL_AUTOMATON = patterns("indices:*", "internal:transport/proxy/indices:*");
private static final Automaton READ_AUTOMATON = patterns("indices:data/read/*");
@ -144,10 +147,12 @@ public final class IndexPrivilege extends Privilege {
} else if (indexPrivilege != null) {
automata.add(indexPrivilege.automaton);
} else {
throw new IllegalArgumentException("unknown index privilege [" + part + "]. a privilege must be either " +
"one of the predefined fixed indices privileges [" +
Strings.collectionToCommaDelimitedString(VALUES.entrySet()) + "] or a pattern over one of the available index" +
" actions");
String errorMessage = "unknown index privilege [" + part + "]. a privilege must be either " +
"one of the predefined fixed indices privileges [" +
Strings.collectionToCommaDelimitedString(VALUES.entrySet()) + "] or a pattern over one of the available index" +
" actions";
logger.debug(errorMessage);
throw new IllegalArgumentException(errorMessage);
}
}
}

View File

@ -41,6 +41,42 @@ import static org.hamcrest.Matchers.nullValue;
public class PutRoleRequestTests extends ESTestCase {
public void testValidationErrorWithUnknownClusterPrivilegeName() {
final PutRoleRequest request = new PutRoleRequest();
request.name(randomAlphaOfLengthBetween(4, 9));
String unknownClusterPrivilegeName = "unknown_" + randomAlphaOfLengthBetween(3,9);
request.cluster("manage_security", unknownClusterPrivilegeName);
// Fail
assertValidationError("unknown cluster privilege [" + unknownClusterPrivilegeName.toLowerCase(Locale.ROOT) + "]", request);
}
public void testValidationSuccessWithCorrectClusterPrivilegeName() {
final PutRoleRequest request = new PutRoleRequest();
request.name(randomAlphaOfLengthBetween(4, 9));
request.cluster("manage_security", "manage", "cluster:admin/xpack/security/*");
assertSuccessfulValidation(request);
}
public void testValidationErrorWithUnknownIndexPrivilegeName() {
final PutRoleRequest request = new PutRoleRequest();
request.name(randomAlphaOfLengthBetween(4, 9));
String unknownIndexPrivilegeName = "unknown_" + randomAlphaOfLengthBetween(3,9);
request.addIndex(new String[]{randomAlphaOfLength(5)}, new String[]{"index", unknownIndexPrivilegeName}, null,
null, null, randomBoolean());
// Fail
assertValidationError("unknown index privilege [" + unknownIndexPrivilegeName.toLowerCase(Locale.ROOT) + "]", request);
}
public void testValidationSuccessWithCorrectIndexPrivilegeName() {
final PutRoleRequest request = new PutRoleRequest();
request.name(randomAlphaOfLengthBetween(4, 9));
request.addIndex(new String[]{randomAlphaOfLength(5)}, new String[]{"index", "write", "indices:data/read"}, null,
null, null, randomBoolean());
assertSuccessfulValidation(request);
}
public void testValidationOfApplicationPrivileges() {
assertSuccessfulValidation(buildRequestWithApplicationPrivilege("app", new String[]{"read"}, new String[]{"*"}));
assertSuccessfulValidation(buildRequestWithApplicationPrivilege("app", new String[]{"action:login"}, new String[]{"/"}));