Skip to content

Commit

Permalink
Merge pull request #307 from ThorodanBrom/apd-mgmt-changes
Browse files Browse the repository at this point in the history
Changes to APD lifecycle management + Removal of Trustee role from server
  • Loading branch information
ThorodanBrom authored Aug 4, 2023
2 parents b3d72d8 + 4ce500c commit 3c07b1e
Show file tree
Hide file tree
Showing 27 changed files with 351 additions and 3,854 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pipeline {
sh 'docker compose -f docker-compose-test.yml up test'
}
xunit (
thresholds: [ skipped(failureThreshold: '14'), failed(failureThreshold: '0') ],
thresholds: [ skipped(failureThreshold: '15'), failed(failureThreshold: '0') ],
tools: [ JUnit(pattern: 'target/surefire-reports/*.xml') ]
)
jacoco classPattern: 'target/classes', execPattern: 'target/jacoco.exec', sourcePattern: 'src/main/java', exclusionPattern:'**/*VertxEBProxy.class,**/Constants.class,**/*VertxProxyHandler.class,**/*Verticle.class,iudx/aaa/server/deploy/*.class,iudx/aaa/server/registration/KcAdmin.class,iudx/aaa/server/apiserver/*,iudx/aaa/server/apiserver/util/*,iudx/aaa/server/admin/AdminService.class,iudx/aaa/server/apd/ApdService.class,iudx/aaa/server/auditing/AuditingService.class,iudx/aaa/server/auditing/AuditingService.class,iudx/aaa/server/registration/RegistrationService.class,iudx/aaa/server/token/TokenService.class,iudx/aaa/server/policy/PolicyService.class'
Expand Down
234 changes: 20 additions & 214 deletions docs/openapi.yaml

Large diffs are not rendered by default.

198 changes: 35 additions & 163 deletions src/main/java/iudx/aaa/server/apd/ApdServiceImpl.java

Large diffs are not rendered by default.

7 changes: 2 additions & 5 deletions src/main/java/iudx/aaa/server/apd/ApdVerticle.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import static iudx.aaa.server.admin.Constants.DB_RECONNECT_ATTEMPTS;
import static iudx.aaa.server.admin.Constants.DB_RECONNECT_INTERVAL_MS;
import static iudx.aaa.server.apd.Constants.REGISTRATION_SERVICE_ADDRESS;
import static iudx.aaa.server.apd.Constants.POLICY_SERVICE_ADDRESS;
import static iudx.aaa.server.apd.Constants.TOKEN_SERVICE_ADDRESS;

import io.vertx.core.AbstractVerticle;
Expand Down Expand Up @@ -67,7 +66,6 @@ public class ApdVerticle extends AbstractVerticle {
private WebClientOptions webClientOptions;
private ApdWebClient apdWebClient;
private RegistrationService registrationService;
private PolicyService policyService;
private TokenService tokenService;

private ApdService apdService;
Expand Down Expand Up @@ -131,10 +129,9 @@ public void start() throws Exception {
apdWebClient = new ApdWebClient(webClient, apdWebCliConfig);

registrationService = RegistrationService.createProxy(vertx, REGISTRATION_SERVICE_ADDRESS);
policyService = PolicyService.createProxy(vertx, POLICY_SERVICE_ADDRESS);
tokenService = TokenService.createProxy(vertx, TOKEN_SERVICE_ADDRESS);
apdService = new ApdServiceImpl(pool, apdWebClient, registrationService, policyService,
tokenService, apdServiceOptions);
apdService = new ApdServiceImpl(pool, apdWebClient, registrationService, tokenService,
apdServiceOptions);
binder = new ServiceBinder(vertx);
consumer = binder.setAddress(APD_SERVICE_ADDRESS).register(ApdService.class, apdService);

Expand Down
24 changes: 7 additions & 17 deletions src/main/java/iudx/aaa/server/apd/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
public class Constants {

public static final String REGISTRATION_SERVICE_ADDRESS = "iudx.aaa.registration.service";
public static final String POLICY_SERVICE_ADDRESS = "iudx.aaa.policy.service";
public static final String TOKEN_SERVICE_ADDRESS = "iudx.aaa.token.service";

public static final String NIL_UUID = "00000000-0000-0000-0000-000000000000";
Expand All @@ -29,8 +28,6 @@ public class Constants {
public static final String RESP_APD_NAME = "name";
public static final String RESP_APD_URL = "url";
public static final String RESP_APD_STATUS = "status";
public static final String RESP_APD_OWNER = "owner";
public static final String RESP_OWNER_USER_ID = "id";
public static final String INTERNALERROR = "internal server error";

/* Response title and details */
Expand All @@ -45,9 +42,6 @@ public class Constants {
public static final String ERR_TITLE_NO_USER_PROFILE = "User profile does not exist";
public static final String ERR_DETAIL_NO_USER_PROFILE = "Please register to create user profile";

public static final String ERR_TITLE_NOT_TRUSTEE = "Not a trustee";
public static final String ERR_DETAIL_NOT_TRUSTEE = "Use does not have the trustee role";

public static final String ERR_TITLE_APD_NOT_RESPOND = "Invalid APD response";
public static final String ERR_DETAIL_APD_NOT_RESPOND =
"The APD is not responsive/has not responded correctly";
Expand All @@ -68,7 +62,7 @@ public class Constants {

public static final String ERR_TITLE_NO_ROLES_PUT = "Invalid roles to call API";
public static final String ERR_DETAIL_NO_ROLES_PUT =
"Trustees and Auth Server Admin may call the API";
"Auth Server Admin may call the API";

public static final String ERR_TITLE_INVALID_REQUEST = "Invalid request";
public static final String ERR_TITLE_INVALID_REQUEST_ID = "APD not present";
Expand All @@ -77,18 +71,15 @@ public class Constants {

/* SQL */
public static final String SQL_INSERT_APD_IF_NOT_EXISTS =
"INSERT INTO apds (name, url, owner_id, status, created_at, updated_at) VALUES "
+ "($1::text, $2::text, $3::uuid, 'PENDING', NOW(), NOW()) "
"INSERT INTO apds (name, url, status, created_at, updated_at) VALUES "
+ "($1::text, $2::text, 'ACTIVE', NOW(), NOW()) "
+ "ON CONFLICT (url) DO NOTHING RETURNING id";

public static final String SQL_CHECK_ADMIN_OF_SERVER =
"SELECT id FROM " + "resource_server WHERE owner_id = $1::uuid AND url = $2::text";

public static final String SQL_GET_APDS_BY_ID_ADMIN =
"SELECT id AS \"apdId\", name, url, owner_id, status FROM apds WHERE id = ANY($1::uuid[])";

public static final String SQL_GET_APDS_BY_ID_TRUSTEE =
"SELECT id AS \"apdId\", name, url, owner_id, status FROM apds WHERE id = ANY($1::uuid[]) AND owner_id = $2::uuid";
"SELECT id AS \"apdId\", name, url, status FROM apds WHERE id = ANY($1::uuid[])";

public static final String SQL_UPDATE_APD_STATUS =
"UPDATE apds SET status = $1::apd_status_enum, updated_at = NOW() WHERE id = $2::uuid";
Expand Down Expand Up @@ -138,9 +129,8 @@ public class Constants {
public static final String APD_NOT_ACTIVE = " (NOTE: The APD is currently not in an active state.)";
public static final String ERR_TITLE_POLICY_EVAL_FAILED = "Policy evaluation failed";

public static final String GET_APDINFO_ID = "SELECT id,name,url,status,owner_id as \"ownerId\" FROM apds where id = ANY($1::uuid[])";
public static final String GET_APDINFO_URL = "SELECT id,name,url,status,owner_id as \"ownerId\" FROM apds where url = ANY($1::text[])";
public static final String LIST_AUTH_QUERY = "SELECT id FROM apds where status = $1::apd_status_enum or status = $2::apd_status_enum or status = $3::apd_status_enum";
public static final String LIST_TRUSTEE_QUERY = "SELECT id FROM apds WHERE (owner_id = $1::UUID OR status = $2::apd_status_enum) ";
public static final String GET_APDINFO_ID = "SELECT id,name,url,status FROM apds where id = ANY($1::uuid[])";
public static final String GET_APDINFO_URL = "SELECT id,name,url,status FROM apds where url = ANY($1::text[])";
public static final String LIST_AUTH_QUERY = "SELECT id FROM apds where status = $1::apd_status_enum or status = $2::apd_status_enum";
public static final String LIST_USER_QUERY = "SELECT id FROM apds WHERE status = $1::apd_status_enum ";
}
10 changes: 0 additions & 10 deletions src/main/java/iudx/aaa/server/apiserver/ApdInfoObj.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ public class ApdInfoObj {
UUID id;
String name;
String url;
UUID ownerId;
ApdStatus status;

public String getId() {
Expand All @@ -37,14 +36,6 @@ public void setUrl(String url) {
this.url = url;
}

public String getOwnerId() {
return ownerId.toString();
}

public void setOwnerId(String ownerId) {
this.ownerId = UUID.fromString(ownerId);
}

public ApdStatus getStatus() {
return status;
}
Expand All @@ -57,7 +48,6 @@ public ApdInfoObj(UUID id, String name, String url, UUID ownerId, ApdStatus stat
this.id = id;
this.name = name;
this.url = url;
this.ownerId = ownerId;
this.status = status;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/iudx/aaa/server/apiserver/ApdStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Enum that defines valid status an Access Policy Domain (APD) can be in.
*/
public enum ApdStatus {
PENDING, ACTIVE, INACTIVE;
ACTIVE, INACTIVE;

static List<String> apdStatusAsStrings =
Arrays.stream(ApdStatus.values()).map(r -> r.name()).collect(Collectors.toList());
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/iudx/aaa/server/apiserver/Roles.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Enum that defines all valid roles recognized by the AAA server.
*/
public enum Roles {
PROVIDER, DELEGATE, TRUSTEE, CONSUMER, ADMIN;
PROVIDER, DELEGATE, CONSUMER, ADMIN;

static List<String> rolesAsStrings =
Arrays.stream(Roles.values()).map(r -> r.name()).collect(Collectors.toList());
Expand Down
116 changes: 5 additions & 111 deletions src/main/java/iudx/aaa/server/policy/PolicyServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,7 @@ public PolicyService createPolicy(

if (!roles.contains(Roles.ADMIN)
&& !roles.contains(Roles.PROVIDER)
&& !roles.contains(Roles.DELEGATE)
&& !roles.contains(Roles.TRUSTEE)) {
&& !roles.contains(Roles.DELEGATE)) {

Response r =
new Response.ResponseBuilder()
Expand Down Expand Up @@ -218,15 +217,6 @@ public PolicyService createPolicy(
.map(CreatePolicyRequest::getItemId)
.collect(Collectors.toList());

// getApdInfo for all apdIds
// if itemType is apdIds, getApdInfo
List<String> apdUrls =
userPolicyRequests.stream()
.filter(
tagObject -> tagObject.getItemType().toUpperCase().equals(itemTypes.APD.toString()))
.map(CreatePolicyRequest::getItemId)
.collect(Collectors.toList());

List<String> resGrpIds =
request.stream()
.filter(
Expand All @@ -249,7 +239,6 @@ public PolicyService createPolicy(
Map<String, List<String>> catItem = new HashMap<>();

// check if resServer itemType, All requests must be resServer, role must contain admin
// if itemType is Apd, all req must be Apd,role must contain Trustee
// if item type neither, for request may have both apd and user policies (catalogueFetch)
if (resServerIds.size() > 0) {
// if request has itemType resourceServer, then all request should be for resource server
Expand All @@ -276,32 +265,6 @@ public PolicyService createPolicy(
return this;
} else catItem.put(RES_SERVER, resServerIds);
} else {
// check if user policy for apd exists
if (apdUrls.size() > 0) {
if (apdUrls.size() != request.size()) {
Response r =
new Response.ResponseBuilder()
.type(URN_INVALID_INPUT)
.title(INVALID_INPUT)
.detail("All requests must be for APD")
.status(400)
.build();
handler.handle(Future.succeededFuture(r.toJson()));
return this;
}
if (!roles.contains(Roles.TRUSTEE)) {
Response r =
new Response.ResponseBuilder()
.type(URN_INVALID_ROLE)
.title(INVALID_ROLE)
.detail(INVALID_ROLE)
.status(403)
.build();
handler.handle(Future.succeededFuture(r.toJson()));
return this;
}
catItem.put(APD, apdUrls);
} else {
if (!roles.contains(Roles.PROVIDER) && !roles.contains(Roles.DELEGATE)) {
Response r =
new Response.ResponseBuilder()
Expand All @@ -316,53 +279,11 @@ public PolicyService createPolicy(
if (resGrpIds.size() > 0) catItem.put(RES_GRP, resGrpIds);
if (resIds.size() > 0) catItem.put(RES, resIds);
}
}

Future<Map<String, ResourceObj>> reqItemDetail;
if (catItem.containsKey(RES_SERVER)) {
reqItemDetail = createPolicy.getResSerDetails(catItem.get(RES_SERVER), user.getUserId());
} else {
if (catItem.containsKey(APD)) {
List<String> urls = catItem.get(APD);
Promise<JsonObject> promise = Promise.promise();
apdService.getApdDetails(urls, List.of(), promise);
reqItemDetail =
promise
.future()
.compose(
apdDetail -> {
Map<String, ResourceObj> apdMap = new HashMap<>();
List<String> failedUrl = new ArrayList<>();
urls.forEach(
url -> {
if (!apdDetail.containsKey(url)) failedUrl.add(url);
else {
JsonObject detail = apdDetail.getJsonObject(url);
//status of the apd is not validated for creating policy by the trustee
JsonObject resObj = new JsonObject();
resObj.put(ITEMTYPE, APD);
resObj.put(ID, detail.getString(ID));
resObj.put(CAT_ID, detail.getString(URL));
resObj.put(
OWNER_ID, detail.getJsonObject(OWNER_DETAILS).getString(ID));
resObj.put("resource_server_id",NIL_UUID);
resObj.put("resource_group_id",NIL_UUID);
apdMap.put(resObj.getString(CAT_ID), new ResourceObj(resObj));
}
});

if (failedUrl.size() > 0) {
Response r =
new ResponseBuilder()
.status(400)
.type(URN_INVALID_INPUT)
.title(INVALID_INPUT)
.detail(failedUrl.toString())
.build();
return Future.failedFuture(new ComposeException(r));
}
return Future.succeededFuture(apdMap);
});
} else // For both apdPolicy and userPolicy
reqItemDetail = catalogueClient.checkReqItems(catItem);
}

Expand Down Expand Up @@ -415,28 +336,7 @@ public PolicyService createPolicy(
return createPolicy.checkAuthPolicy(user.getUserId());
});

// to create a policy in the apd_polcies table, user must have a policy by the dataTrustee for the apdId
Future<Boolean> checkTrusteeAuthPolicy =
ItemChecks.compose(obj ->
{
if(validApd.result().isEmpty())
return Future.succeededFuture(true);
else
{
Set<UUID> apdIds = new HashSet<UUID>();
List<String> urls =
apdPolicyRequests.stream().map(CreatePolicyRequest::getApdId).collect(Collectors.toList());
urls.forEach(url ->
{
apdIds.add(UUID.fromString(validApd.result().getJsonObject(url).getString(ID)));
});
return createPolicy.checkAuthTrusteePolicy(providerId, apdIds);
}
}
);


Future<List<UUID>> checkDelegate = CompositeFuture.all(checkAuthPolicy,checkTrusteeAuthPolicy).compose(
Future<List<UUID>> checkDelegate = checkAuthPolicy.compose(
checkAut -> {
if (checkAut.equals(false)) return Future.succeededFuture(new ArrayList<>());
List<ResourceObj> resourceObj = new ArrayList<>(reqItemDetail.result().values());
Expand Down Expand Up @@ -537,7 +437,7 @@ public PolicyService deletePolicy(JsonArray request, User user, JsonObject data,
List<Roles> roles = user.getRoles();

if (!roles.contains(Roles.ADMIN) && !roles.contains(Roles.PROVIDER)
&& !roles.contains(Roles.DELEGATE) && ! roles.contains(Roles.TRUSTEE)) {
&& !roles.contains(Roles.DELEGATE)) {
// cannot create policy
Response r = new Response.ResponseBuilder().type(URN_INVALID_ROLE).title(INVALID_ROLE)
.detail(INVALID_ROLE).status(401).build();
Expand Down Expand Up @@ -637,14 +537,8 @@ public PolicyService listPolicy(User user, JsonObject data,

List<String> userIds = new ArrayList<String>(userIdSet);

/*
* For APD IDs get IDs from policies where the item type is APD and from the APD IDs in
* APD policies
*/
Set<String> apdIdSet = itemTypeToIds.get(itemTypes.APD).stream().map(id -> id.toString())
Set<String> apdIdSet = apdPolicies.result().stream().map(j -> j.getString(APD_ID))
.collect(Collectors.toSet());
apdIdSet.addAll(apdPolicies.result().stream().map(j -> j.getString(APD_ID))
.collect(Collectors.toSet()));

List<String> apdIds = new ArrayList<String>(apdIdSet);

Expand Down
30 changes: 0 additions & 30 deletions src/main/java/iudx/aaa/server/policy/createPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -369,36 +369,6 @@ public Future<Boolean> checkAuthPolicy(String userId) {
return p.future();
}

public Future<Boolean> checkAuthTrusteePolicy(String providerId, Set<UUID> apdIds) {
Promise<Boolean> p = Promise.promise();
pool.withConnection(
conn ->
conn.preparedQuery(CHECK_TRUSTEE_POLICY)
.execute(Tuple.of(providerId, status.ACTIVE, apdIds.toArray(UUID[]::new)))
.onFailure(
obj -> {
LOGGER.error(
"checkAuthTrusteePolicy db fail :: " + obj.getLocalizedMessage());
p.fail(INTERNALERROR);
})
.onSuccess(
obj -> {
if (obj.rowCount() == apdIds.size()) p.complete(true);
else {
Response r =
new Response.ResponseBuilder()
.type(URN_INVALID_INPUT)
.title(NO_AUTH_TRUSTEE_POLICY)
.detail(NO_AUTH_TRUSTEE_POLICY)
.status(403)
.build();
p.fail(new ComposeException(r));
}
}));

return p.future();
}

public Future<List<Tuple>> userPolicyDuplicate(
List<CreatePolicyRequest> req, Map<String, ResourceObj> resourceObj, User user) {
Promise<List<Tuple>> p = Promise.promise();
Expand Down
Loading

0 comments on commit 3c07b1e

Please sign in to comment.