Skip to content

Commit dbeb0a0

Browse files
authored
feat(access-control-service): AccessControlService added as a new micro service (#3767)
## Overview This PR is fixing the first part of [#3634](#3634). The full [PR](#3598) had so many changes so we broke it down into two PRs. This PR is the first one that introduce Access Control Service only without its usage in any part of the system. ## Test cases - Empty authorization token - Wrong CUID format - Request access for a user without access to the computing unit - Request access for a user with access to the computing unit ## Changes Currently, the folder named `access-control-service` is added with its dependencies to `auth` folder. Currently, it has test cases to make sure its functionality is working correctly. <img width="1382" height="554" alt="Screenshot from 2025-09-25 15-46-55" src="https://github.com/user-attachments/assets/25da27b4-5018-4a47-bccc-6ba2adacbfb4" /> | Component/Flow | File | Description | | :--- | :--- | :--- | | **New `AccessControl` Service** | `core/access-control-service/...` | A new Dropwizard-based microservice responsible for authorizing user requests to computing units. This includes its build configuration, application setup (`AccessControlService.scala`), configuration model (`AccessControlServiceConfiguration.scala`), authorization logic, REST endpoint (`AccessControlResource.scala`), and unit tests (`AccessControlResourceSpec.scala`). | | **Database Access Logic** | `core/auth/src/main/scala/edu/uci/ics/texera/auth/util/ComputingUnitAccess.scala` | Implements the logic to query the PostgreSQL database and determine a user's access privilege (`READ`, `WRITE`, `NONE`) for a given Computing Unit. | | | `core/auth/src/main/scala/edu/uci/ics/texera/auth/util/HeaderField.scala` | Defines constants for the custom HTTP headers (`x-user-cu-access`, `x-user-id`, etc.) that are injected by the Access Control Service. |
1 parent f90848e commit dbeb0a0

File tree

13 files changed

+763
-0
lines changed

13 files changed

+763
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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+
18+
import scala.collection.Seq
19+
20+
name := "access-control-service"
21+
organization := "edu.uci.ics"
22+
version := "1.0.0"
23+
24+
scalaVersion := "2.13.12"
25+
26+
enablePlugins(JavaAppPackaging)
27+
28+
// Enable semanticdb for Scalafix
29+
ThisBuild / semanticdbEnabled := true
30+
ThisBuild / semanticdbVersion := scalafixSemanticdb.revision
31+
32+
// Manage dependency conflicts by always using the latest revision
33+
ThisBuild / conflictManager := ConflictManager.latestRevision
34+
35+
// Restrict parallel execution of tests to avoid conflicts
36+
Global / concurrentRestrictions += Tags.limit(Tags.Test, 1)
37+
38+
/////////////////////////////////////////////////////////////////////////////
39+
// Compiler Options
40+
/////////////////////////////////////////////////////////////////////////////
41+
42+
// Scala compiler options
43+
Compile / scalacOptions ++= Seq(
44+
"-Xelide-below", "WARNING", // Turn on optimizations with "WARNING" as the threshold
45+
"-feature", // Check feature warnings
46+
"-deprecation", // Check deprecation warnings
47+
"-Ywarn-unused:imports" // Check for unused imports
48+
)
49+
50+
/////////////////////////////////////////////////////////////////////////////
51+
// Version Variables
52+
/////////////////////////////////////////////////////////////////////////////
53+
54+
val dropwizardVersion = "4.0.7"
55+
val mockitoVersion = "5.4.0"
56+
val assertjVersion = "3.24.2"
57+
58+
/////////////////////////////////////////////////////////////////////////////
59+
// Test-related Dependencies
60+
/////////////////////////////////////////////////////////////////////////////
61+
62+
libraryDependencies ++= Seq(
63+
"org.scalamock" %% "scalamock" % "5.2.0" % Test, // ScalaMock
64+
"org.scalatest" %% "scalatest" % "3.2.17" % Test, // ScalaTest
65+
"io.dropwizard" % "dropwizard-testing" % dropwizardVersion % Test, // Dropwizard Testing
66+
"org.mockito" % "mockito-core" % mockitoVersion % Test, // Mockito for mocking
67+
"org.assertj" % "assertj-core" % assertjVersion % Test, // AssertJ for assertions
68+
"com.novocode" % "junit-interface" % "0.11" % Test // SBT interface for JUnit
69+
)
70+
71+
/////////////////////////////////////////////////////////////////////////////
72+
// Dependencies
73+
/////////////////////////////////////////////////////////////////////////////
74+
75+
// Core Dependencies
76+
libraryDependencies ++= Seq(
77+
"io.dropwizard" % "dropwizard-core" % dropwizardVersion,
78+
"io.dropwizard" % "dropwizard-auth" % dropwizardVersion, // Dropwizard Authentication module
79+
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.15.2",
80+
"org.playframework" %% "play-json" % "3.1.0-M1",
81+
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
18+
sbt.version = 1.9.9
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
18+
server:
19+
applicationConnectors:
20+
- type: http
21+
port: 9096
22+
adminConnectors: []
23+
24+
logging:
25+
level: INFO
26+
appenders:
27+
- type: console
28+
threshold: INFO
29+
- type: file
30+
currentLogFilename: logs/access-control-service.log
31+
archive: true
32+
archivedLogFilenamePattern: logs/access-control-service-%d.log.gz
33+
archivedFileCount: 5
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<!--
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
20+
<configuration>
21+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
22+
<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder
23+
by default -->
24+
<encoder>
25+
<pattern>[%date{ISO8601}] [%level] [%logger] [%thread] - %msg %n
26+
</pattern>
27+
</encoder>
28+
</appender>
29+
30+
31+
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
32+
<file>../log/access-control-service.log</file>
33+
<immediateFlush>true</immediateFlush>
34+
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
35+
<fileNamePattern>../log/access-control-service-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
36+
</rollingPolicy>
37+
<encoder>
38+
<pattern>[%date{ISO8601}] [%level] [%logger] [%thread] - %msg %n</pattern>
39+
</encoder>
40+
</appender>
41+
42+
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
43+
<queueSize>8192</queueSize>
44+
<neverBlock>true</neverBlock>
45+
<appender-ref ref="FILE"/>
46+
</appender>
47+
48+
<root level="INFO">
49+
<appender-ref ref="ASYNC"/>
50+
<appender-ref ref="STDOUT"/>
51+
</root>
52+
<logger name="org.apache" level="WARN"/>
53+
<logger name="httpclient" level="WARN"/>
54+
<logger name="io.grpc.netty" level="WARN"/>
55+
</configuration>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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+
18+
package edu.uci.ics.texera.service
19+
20+
import io.dropwizard.core.Application
21+
import io.dropwizard.core.setup.{Bootstrap, Environment}
22+
import com.fasterxml.jackson.module.scala.DefaultScalaModule
23+
import com.typesafe.scalalogging.LazyLogging
24+
import edu.uci.ics.amber.config.StorageConfig
25+
import edu.uci.ics.amber.util.PathUtils.{configServicePath, accessControlServicePath}
26+
import edu.uci.ics.texera.auth.{JwtAuthFilter, SessionUser}
27+
import edu.uci.ics.texera.dao.SqlServer
28+
import edu.uci.ics.texera.service.resource.{HealthCheckResource, AccessControlResource}
29+
import io.dropwizard.auth.AuthDynamicFeature
30+
import org.eclipse.jetty.server.session.SessionHandler
31+
import org.jooq.impl.DSL
32+
33+
34+
class AccessControlService extends Application[AccessControlServiceConfiguration] with LazyLogging {
35+
override def initialize(bootstrap: Bootstrap[AccessControlServiceConfiguration]): Unit = {
36+
// Register Scala module to Dropwizard default object mapper
37+
bootstrap.getObjectMapper.registerModule(DefaultScalaModule)
38+
39+
SqlServer.initConnection(
40+
StorageConfig.jdbcUrl,
41+
StorageConfig.jdbcUsername,
42+
StorageConfig.jdbcPassword
43+
)
44+
}
45+
46+
override def run(configuration: AccessControlServiceConfiguration, environment: Environment): Unit = {
47+
// Serve backend at /api
48+
environment.jersey.setUrlPattern("/api/*")
49+
50+
environment.jersey.register(classOf[SessionHandler])
51+
environment.servlets.setSessionHandler(new SessionHandler)
52+
53+
environment.jersey.register(classOf[HealthCheckResource])
54+
environment.jersey.register(classOf[AccessControlResource])
55+
56+
// Register JWT authentication filter
57+
environment.jersey.register(new AuthDynamicFeature(classOf[JwtAuthFilter]))
58+
59+
// Enable @Auth annotation for injecting SessionUser
60+
environment.jersey.register(
61+
new io.dropwizard.auth.AuthValueFactoryProvider.Binder(classOf[SessionUser])
62+
)
63+
}
64+
}
65+
object AccessControlService {
66+
def main(args: Array[String]): Unit = {
67+
val accessControlPath = accessControlServicePath
68+
.resolve("src")
69+
.resolve("main")
70+
.resolve("resources")
71+
.resolve("access-control-service-web-config.yaml")
72+
.toAbsolutePath
73+
.toString
74+
75+
// Start the Dropwizard application
76+
new AccessControlService().run("server", accessControlPath)
77+
}
78+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
18+
package edu.uci.ics.texera.service
19+
20+
import io.dropwizard.core.Configuration
21+
22+
class AccessControlServiceConfiguration extends Configuration {}

0 commit comments

Comments
 (0)