Skip to content
Snippets Groups Projects
Commit f1730eb4 authored by Henrik tom Wörden's avatar Henrik tom Wörden
Browse files

Merge branch 'f-transaction-permissions' into 'dev'

fixing server issue #196

See merge request !84
parents 4988aa3f d6087a3e
No related branches found
No related tags found
2 merge requests!96DOC: Added CITATION.cff to the list of files in the release guide where the...,!84fixing server issue #196
Pipeline #35605 failed
......@@ -32,11 +32,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ###
* Denying a role permission has no effect
[#196](https://gitlab.com/caosdb/caosdb-server/-/issues/196). See security
notes below.
* Missing RecordType leads to unexpected server error
[#166](https://gitlab.com/caosdb/caosdb-server/-/issues/166)
### Security ###
* Fixed [#196](https://gitlab.com/caosdb/caosdb-server/-/issues/196). This was
an error in the authorization procedure which allowed unprivileged users
execute insert, update or delete transactions on entities. However, the
unprivileged users would also need the correct entity permissions to do that.
Without backup, this means possible data loss. Also there was the possibility
to spam the database by creating unwanted entities.
### Documentation ###
- Nested queries.
......
......@@ -7,6 +7,7 @@
* `>=Java 11`
* `>=Apache Maven 3.6.0`
* `>=Make 4.2`
* `>=gcc 8` (if PAM authentication is required)
* `libpam` (if PAM authentication is required)
* More dependencies are being pulled and installed automatically by Maven. See the complete list of dependencies in the [pom.xml](pom.xml)
......
......@@ -15,12 +15,18 @@ See [DEPENDENCIES.md](DEPENDENCIES.md).
On Debian, the required packages can be installed with:
apt-get install git make mariadb-server maven openjdk-11-jdk-headless \
python3-pip screen libpam0g-dev unzip
apt-get install make mariadb-server maven openjdk-11-jdk-headless \
python3-pip libpam0g-dev unzip
Note that installing MariaDB will uninstall existing MySQL packages and vice
versa.
#### Install the requirements on Fedora
On Fedora, the required packages can be installed with:
sudo dnf install make pam-devel mariadb-server mariadb python3 java-17-openjdk-headless unzip gcc
### System
* `>=Linux 4.0.0`, `x86_64`, e.g. Ubuntu 18.04
......@@ -160,20 +166,47 @@ sources (if you called `make run` previously).
## Setup Eclipse
1. Open Eclipse (recommended version: Oxygen.1a Release (4.7.1a))
2. `File > New > Java Project`: Choose a project name and specify the location
of this repo. The JRE and Project layout should be configured automatically.
Now, the project should initially have two source-folders: `./src/main/java`
and `./src/test/java`. After a build, another one,
`./target/generated-sources/antlr4` should be generated. If there are more
than these three source-folders, reconfigure the projects source folders
appropriately with `Project > Properties > Java Build Path > Source`.
3. In the `Package Explorer` view, right-click on the project and `Configure >
Convert to Maven Project`.
4. In the `Package Explorer` view, right-click on the project and `Maven >
Update Project`.
5. Usually a build of the project is started automatically. Otherwise `Project >
Build Project`.
1. Open Eclipse (tested with 2022-R12)
2. File > Import > Maven > Existing Maven Projects: Specify location.
3. You will most likely encounter "Plugin execution not covered by lifecycle
configuration: ..." errors. Adapt the file
`<eclipse-workspace>/.metadata/.plugins/org.eclipse.m2e.core/lifecycle-mapping-metadata.xml`.
Example:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>com.coveo</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<versionRange>2.5.1</versionRange>
<goals>
<goal>format</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<versionRange>1.4</versionRange>
<goals>
<goal>create-metadata</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
```
Done!
......
......@@ -67,7 +67,7 @@ MYSQL_DATABASE_NAME=caosdb
# User name for connecting to mysql
MYSQL_USER_NAME=caosdb
# Password for the user
MYSQL_USER_PASSWORD=caosdb
MYSQL_USER_PASSWORD=random1234
# Schema of mysql procedures and tables which is required by this CaosDB instance
MYSQL_SCHEMA_VERSION=v5.0
......
/*
* ** header v3.0
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2018 Research Group Biomedical Physics,
* Max-Planck-Institute for Dynamics and Self-Organization Göttingen
* Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2023 IndiScale <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
......@@ -17,17 +18,17 @@
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ** end header
*/
package org.caosdb.server.jobs.core;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.caosdb.server.accessControl.ACMPermissions;
import org.caosdb.server.database.backend.transaction.RetrieveSparseEntity;
import org.caosdb.server.entity.DeleteEntity;
import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.entity.wrapper.Parent;
import org.caosdb.server.entity.InsertEntity;
import org.caosdb.server.entity.Role;
import org.caosdb.server.entity.UpdateEntity;
import org.caosdb.server.jobs.ContainerJob;
import org.caosdb.server.jobs.JobAnnotation;
import org.caosdb.server.jobs.TransactionStage;
......@@ -35,6 +36,14 @@ import org.caosdb.server.transaction.Retrieve;
import org.caosdb.server.utils.EntityStatus;
import org.caosdb.server.utils.ServerMessages;
/**
* Checks the TRANSACTION:* permissions before a transaction begins.
*
* <p>Users need TRANSACTION:INSERT:?ENTITY_ROLE? permission to insert an entity of the particular
* entity role. Likewise, they need the TRANSACTION:UPDATE or TRANSACTION:DELETE permissions.
*
* @author Timm Fitschen <f.fitschen@indiscale.com>
*/
@JobAnnotation(stage = TransactionStage.INIT)
public class AccessControl extends ContainerJob {
......@@ -46,12 +55,15 @@ public class AccessControl extends ContainerJob {
super(permission, description);
}
public final String toString(String entityRole) {
return toString().replace(ENTITY_ROLE_PARAMETER, entityRole);
public final String toString(Role entityRole) {
String roleString = entityRole == null ? "" : entityRole.toString();
return toString().replace(ENTITY_ROLE_PARAMETER, roleString);
}
public final String toString(String transaction, String entityRole) {
return "TRANSACTION:" + transaction + (entityRole != null ? (":" + entityRole) : "");
public final String toString(String transaction, Role entityRole) {
return "TRANSACTION:"
+ transaction
+ (entityRole != null ? (":" + entityRole.toString()) : "");
}
public static String init() {
......@@ -80,38 +92,26 @@ public class AccessControl extends ContainerJob {
protected void run() {
final Subject subject = SecurityUtils.getSubject();
// subject has complete permissions for this kind of transaction
if (subject.isPermitted(
TRANSACTION_PERMISSIONS.toString(getTransaction().getClass().getSimpleName(), null))) {
return;
}
if (getTransaction() instanceof Retrieve) {
return;
}
for (final EntityInterface e : getContainer()) {
// per role permission
if (subject.isPermitted(
TRANSACTION_PERMISSIONS.toString(
getTransaction().getClass().getSimpleName(), e.getRole().toString()))) {
if (e instanceof InsertEntity) {
if (subject.isPermitted(INSERT.toString(e.getRole()))) {
continue;
}
// special annotations permission
if (e.hasParents() && e.getParents().size() == 1) {
final Parent par1 = e.getParents().get(0);
if (par1.hasId() && !par1.getId().isTemporary()) {
execute(new RetrieveSparseEntity(par1));
} else if (e instanceof DeleteEntity) {
if (subject.isPermitted(DELETE.toString(e.getRole()))) {
continue;
}
if (par1.hasName()
&& par1.getName().equals("CommentAnnotation")
&& subject.isPermitted(
getTransaction().getClass().getSimpleName() + ":CommentAnnotation")) {
} else if (e instanceof UpdateEntity) {
if (subject.isPermitted(UPDATE.toString(e.getRole()))) {
continue;
}
}
e.setEntityStatus(EntityStatus.UNQUALIFIED);
e.addMessage(ServerMessages.AUTHORIZATION_ERROR);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment