Skip to content

Commit

Permalink
Merge pull request #1 from uc-cdis/feat/add_team_project_access_control
Browse files Browse the repository at this point in the history
Feat/add team project access control
  • Loading branch information
rkboyce authored Feb 10, 2024
2 parents 3f9e90c + f6acf94 commit 9e6e3c0
Show file tree
Hide file tree
Showing 18 changed files with 485 additions and 42 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/image_build_push.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Build Image and Push to Quay

on: push

jobs:
ci:
name: Build Image and Push to Quay
uses: uc-cdis/.github/.github/workflows/image_build_push.yaml@master
with:
OVERRIDE_REPO_NAME: "ohdsi-webapi"
BUILD_PLATFORMS: "linux/amd64"
secrets:
ECR_AWS_ACCESS_KEY_ID: ${{ secrets.ECR_AWS_ACCESS_KEY_ID }}
ECR_AWS_SECRET_ACCESS_KEY: ${{ secrets.ECR_AWS_SECRET_ACCESS_KEY }}
QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }}
QUAY_ROBOT_TOKEN: ${{ secrets.QUAY_ROBOT_TOKEN }}
22 changes: 17 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ RUN mvn package ${MAVEN_PARAMS} \
&& jar -xf WebAPI.war \
&& rm WebAPI.war

# OHDSI WebAPI and ATLAS web application running as a Spring Boot application with Java 11
FROM openjdk:8-jre-slim

MAINTAINER Lee Evans - www.ltscomputingllc.com
# OHDSI WebAPI and ATLAS web application running as a Spring Boot application with Java 8
FROM amazoncorretto:8u402-al2023

# Any Java options to pass along, e.g. memory, garbage collection, etc.
ENV JAVA_OPTS=""
Expand All @@ -59,7 +57,21 @@ COPY --from=builder /code/war/META-INF META-INF

EXPOSE 8080

USER 101
#USER 0

RUN echo $JAVA_HOME && mkdir /usr/local/share/aws-certs \
&& curl https://truststore.pki.rds.amazonaws.com/us-east-1/us-east-1-bundle.pem -o /usr/local/share/aws-certs/us-east-1-bundle.pem \
&& cd $JAVA_HOME/jre/lib/security \
&& keytool -import -trustcacerts -storepass changeit -noprompt -alias aws -file /usr/local/share/aws-certs/us-east-1-bundle.pem

#USER 101

# Copy your custom CA certificates to the container
RUN cp /usr/local/share/aws-certs/us-east-1-bundle.pem /etc/pki/ca-trust/source/anchors/

# Update the CA certificate store
RUN update-ca-trust


# Directly run the code as a WAR.
CMD exec java ${DEFAULT_JAVA_OPTS} ${JAVA_OPTS} \
Expand Down
6 changes: 4 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
<spring.batch.repository.isolationLevelForCreate>ISOLATION_READ_COMMITTED</spring.batch.repository.isolationLevelForCreate>
<spring.profiles.active>default</spring.profiles.active>

<security.ohdsi.custom.authorization.mode>teamproject</security.ohdsi.custom.authorization.mode>
<security.ohdsi.custom.authorization.url>http://arborist-service/auth/mapping</security.ohdsi.custom.authorization.url>
<security.provider>DisabledSecurity</security.provider>
<security.token.expiration>43200</security.token.expiration>
<security.origin>http://localhost</security.origin>
Expand Down Expand Up @@ -191,7 +193,7 @@
<!-- If defaultGlobalReadPermissions is set to true (default), then all users can see every artifact. -->
<!-- If it is set to false, WebAPI will filter out the artifacts that a user does not explicitly have -->
<!-- read permissions to -->
<security.defaultGlobalReadPermissions>true</security.defaultGlobalReadPermissions>
<security.defaultGlobalReadPermissions>false</security.defaultGlobalReadPermissions>

<!-- EMBEDDED SERVER CONFIGURATION (ServerProperties) -->
<server.port>8080</server.port>
Expand Down Expand Up @@ -229,7 +231,7 @@
<spring.jpa.properties.hibernate.jdbc.batch_size>200</spring.jpa.properties.hibernate.jdbc.batch_size>
<spring.jpa.properties.hibernate.order_inserts>true</spring.jpa.properties.hibernate.order_inserts>
<logging.level.root>info</logging.level.root>
<logging.level.org.ohdsi>info</logging.level.org.ohdsi>
<logging.level.org.ohdsi>debug</logging.level.org.ohdsi>
<logging.level.org.springframework.orm>info</logging.level.org.springframework.orm>
<logging.level.org.springframework.jdbc>info</logging.level.org.springframework.jdbc>
<logging.level.org.springframework.web>info</logging.level.org.springframework.web>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ public boolean hasReadAccess(CommonEntity entity) {
try {
String login = this.permissionManager.getSubjectName();
UserSimpleAuthorizationInfo authorizationInfo = this.permissionManager.getAuthorizationInfo(login);
if (Objects.equals(authorizationInfo.getUserId(), entity.getCreatedBy().getId())){
hasAccess = true; // the role is the one that created the artifact
} else {
// if (Objects.equals(authorizationInfo.getUserId(), entity.getCreatedBy().getId())){
// hasAccess = true; // the role is the one that created the artifact - Is this for backwards compatibiliy mode? Should we write a migration instead?
// } else {
EntityType entityType = entityPermissionSchemaResolver.getEntityType(entity.getClass());

List<RoleDTO> roles = getRolesHavingReadPermissions(entityType, entity.getId());
Expand All @@ -296,7 +296,7 @@ public boolean hasReadAccess(CommonEntity entity) {
hasAccess = roles.stream()
.anyMatch(r -> userRoles.stream()
.anyMatch(re -> re.equals(r.getName())));
}
// }
} catch (Exception e) {
logger.error("Error getting user roles and permissions", e);
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@

import org.ohdsi.webapi.model.CommonEntity;
import org.ohdsi.webapi.shiro.Entities.RoleEntity;
import org.ohdsi.webapi.shiro.filters.UpdateAccessTokenFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ohdsi.webapi.shiro.PermissionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public abstract class EntityPermissionSchema {
private final Logger logger = LoggerFactory.getLogger(UpdateAccessTokenFilter.class);

private final EntityType entityType;
private final Map<String, String> readPermissions;
private final Map<String, String> writePermissions;

@Value("${security.ohdsi.custom.authorization.mode}")
private String authorizationMode;

@Autowired
protected PermissionManager permissionManager;

Expand Down Expand Up @@ -49,8 +57,12 @@ public Map<String, String> getAllPermissions() {
}

public void onInsert(CommonEntity commonEntity) {

addPermissionsToCurrentUserFromTemplate(commonEntity, getAllPermissions());
logger.debug("AUTHORIZATION_MODE in EntityPermissionSchema == '{}'", this.authorizationMode);
if (this.authorizationMode.equals("teamproject")) {
addPermissionsToCurrentTeamProjectFromTemplate(commonEntity, getAllPermissions());
} else {
addPermissionsToCurrentUserFromTemplate(commonEntity, getAllPermissions());
}
}

public void onDelete(CommonEntity commonEntity) {
Expand All @@ -65,4 +77,13 @@ protected void addPermissionsToCurrentUserFromTemplate(CommonEntity commonEntity
RoleEntity role = permissionManager.getUserPersonalRole(login);
permissionManager.addPermissionsFromTemplate(role, template, commonEntity.getId().toString());
}

protected void addPermissionsToCurrentTeamProjectFromTemplate(CommonEntity commonEntity, Map<String, String> template) {

RoleEntity role = permissionManager.getCurrentTeamProjectRoleForCurrentUser();
if (role == null) {
throw new RuntimeException("Expected a teamproject role but found none!");
}
permissionManager.addPermissionsFromTemplate(role, template, commonEntity.getId().toString());
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/ohdsi/webapi/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public Role createRole(Role role) throws Exception {
public Role updateRole(@PathParam("roleId") Long id, Role role) throws Exception {
RoleEntity roleEntity = this.authorizer.getRole(id);
if (roleEntity == null) {
throw new Exception("Role doesn't exist");
throw new Exception("Role doesn't exist: " + id);
}
roleEntity.setName(role.role);
roleEntity = this.authorizer.updateRole(roleEntity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,9 @@ public UserOrigin getOrigin() {
public void setOrigin(UserOrigin origin) {
this.origin = origin;
}

public String toString() {
role = this.getRole();
return (role != null ? role.getName() : "");
}
}
Loading

0 comments on commit 9e6e3c0

Please sign in to comment.