879 |
879 |
*
|
880 |
880 |
* @param session - the Session object containing the credentials for the Subject
|
881 |
881 |
*
|
882 |
|
* @return true if the user is admin
|
|
882 |
* @return true if the user is admin (mn itself or a cn )
|
883 |
883 |
*
|
884 |
884 |
* @throws ServiceFailure
|
885 |
885 |
* @throws InvalidToken
|
... | ... | |
907 |
907 |
|
908 |
908 |
// check the CN list
|
909 |
909 |
if (!allowed) {
|
910 |
|
List<Node> nodes = null;
|
|
910 |
allowed = isCNAdmin(session);
|
|
911 |
}
|
|
912 |
|
|
913 |
return allowed;
|
|
914 |
}
|
|
915 |
|
|
916 |
/*
|
|
917 |
* Determine if the specified session is a CN or not. Return true if it is; otherwise false.
|
|
918 |
*/
|
|
919 |
protected boolean isCNAdmin (Session session) {
|
|
920 |
boolean allowed = false;
|
|
921 |
List<Node> nodes = null;
|
911 |
922 |
|
912 |
|
try {
|
913 |
|
// are we allowed to do this? only CNs are allowed
|
914 |
|
CNode cn = D1Client.getCN();
|
915 |
|
nodes = cn.listNodes().getNodeList();
|
916 |
|
}
|
917 |
|
catch (Throwable e) {
|
918 |
|
logMetacat.warn(e.getMessage());
|
919 |
|
return false;
|
920 |
|
}
|
921 |
|
|
922 |
|
if ( nodes == null ) {
|
923 |
|
return false;
|
924 |
|
//throw new ServiceFailure("4852", "Couldn't get node list.");
|
925 |
|
}
|
926 |
|
|
927 |
|
// find the node in the node list
|
928 |
|
for ( Node node : nodes ) {
|
929 |
|
|
930 |
|
NodeReference nodeReference = node.getIdentifier();
|
931 |
|
logMetacat.debug("In isAdminAuthorized(), Node reference is: " + nodeReference.getValue());
|
932 |
|
|
933 |
|
Subject subject = session.getSubject();
|
934 |
|
|
935 |
|
if (node.getType() == NodeType.CN) {
|
936 |
|
List<Subject> nodeSubjects = node.getSubjectList();
|
937 |
|
|
938 |
|
// check if the session subject is in the node subject list
|
939 |
|
for (Subject nodeSubject : nodeSubjects) {
|
940 |
|
logMetacat.debug("In isAdminAuthorized(), comparing subjects: " +
|
941 |
|
nodeSubject.getValue() + " and " + subject.getValue());
|
942 |
|
if ( nodeSubject.equals(subject) ) {
|
943 |
|
allowed = true; // subject of session == target node subject
|
944 |
|
break;
|
945 |
|
|
946 |
|
}
|
947 |
|
}
|
948 |
|
}
|
949 |
|
}
|
|
923 |
try {
|
|
924 |
// are we allowed to do this? only CNs are allowed
|
|
925 |
CNode cn = D1Client.getCN();
|
|
926 |
nodes = cn.listNodes().getNodeList();
|
950 |
927 |
}
|
|
928 |
catch (Throwable e) {
|
|
929 |
logMetacat.warn(e.getMessage());
|
|
930 |
return false;
|
|
931 |
}
|
|
932 |
|
|
933 |
if ( nodes == null ) {
|
|
934 |
return false;
|
|
935 |
//throw new ServiceFailure("4852", "Couldn't get node list.");
|
|
936 |
}
|
951 |
937 |
|
|
938 |
// find the node in the node list
|
|
939 |
for ( Node node : nodes ) {
|
|
940 |
|
|
941 |
NodeReference nodeReference = node.getIdentifier();
|
|
942 |
logMetacat.debug("In isAdminAuthorized(), Node reference is: " + nodeReference.getValue());
|
|
943 |
|
|
944 |
Subject subject = session.getSubject();
|
|
945 |
|
|
946 |
if (node.getType() == NodeType.CN) {
|
|
947 |
List<Subject> nodeSubjects = node.getSubjectList();
|
|
948 |
|
|
949 |
// check if the session subject is in the node subject list
|
|
950 |
for (Subject nodeSubject : nodeSubjects) {
|
|
951 |
logMetacat.debug("In isAdminAuthorized(), comparing subjects: " +
|
|
952 |
nodeSubject.getValue() + " and " + subject.getValue());
|
|
953 |
if ( nodeSubject.equals(subject) ) {
|
|
954 |
allowed = true; // subject of session == target node subject
|
|
955 |
break;
|
|
956 |
|
|
957 |
}
|
|
958 |
}
|
|
959 |
}
|
|
960 |
}
|
952 |
961 |
return allowed;
|
953 |
962 |
}
|
954 |
963 |
|
... | ... | |
1030 |
1039 |
throw new InvalidRequest("1761", "Permission was not provided or is invalid");
|
1031 |
1040 |
}
|
1032 |
1041 |
|
1033 |
|
// permissions are hierarchical
|
1034 |
|
List<Permission> expandedPermissions = null;
|
1035 |
|
|
1036 |
1042 |
// always allow CN access
|
1037 |
1043 |
if ( isAdminAuthorized(session) ) {
|
1038 |
1044 |
allowed = true;
|
... | ... | |
1052 |
1058 |
return allowed;
|
1053 |
1059 |
}
|
1054 |
1060 |
|
1055 |
|
// get the subject[s] from the session
|
1056 |
|
//defer to the shared util for recursively compiling the subjects
|
1057 |
|
Set<Subject> subjects = AuthUtils.authorizedClientSubjects(session);
|
|
1061 |
//is it the owner of the object or the access rules allow the user?
|
|
1062 |
allowed = userHasPermission(session, pid, permission );
|
1058 |
1063 |
|
1059 |
|
// track the identities we have checked against
|
1060 |
|
StringBuffer includedSubjects = new StringBuffer();
|
1061 |
|
|
1062 |
|
// get the system metadata
|
1063 |
|
String pidStr = pid.getValue();
|
1064 |
|
SystemMetadata systemMetadata = null;
|
1065 |
|
try {
|
1066 |
|
systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
|
1067 |
|
|
1068 |
|
} catch (Exception e) {
|
1069 |
|
// convert Hazelcast RuntimeException to NotFound
|
1070 |
|
logMetacat.error("An error occurred while getting system metadata for identifier " +
|
1071 |
|
pid.getValue() + ". The error message was: " + e.getMessage());
|
1072 |
|
throw new NotFound("1800", "No record found for " + pidStr);
|
1073 |
|
|
1074 |
|
}
|
1075 |
|
|
1076 |
|
// throw not found if it was not found
|
1077 |
|
if (systemMetadata == null) {
|
1078 |
|
String localId = null;
|
1079 |
|
String error = "No system metadata could be found for given PID: " + pidStr;
|
1080 |
|
try {
|
1081 |
|
localId = IdentifierManager.getInstance().getLocalId(pid.getValue());
|
1082 |
|
|
1083 |
|
} catch (Exception e) {
|
1084 |
|
logMetacat.warn("Couldn't find the local id for the pid "+pidStr);
|
1085 |
|
}
|
1086 |
|
|
1087 |
|
if(localId != null && EventLog.getInstance().isDeleted(localId)) {
|
1088 |
|
error = error + ". "+DELETEDMESSAGE;
|
1089 |
|
} else if (localId == null && EventLog.getInstance().isDeleted(pid.getValue())) {
|
1090 |
|
error = error + ". "+DELETEDMESSAGE;
|
1091 |
|
}
|
1092 |
|
throw new NotFound("1800", error);
|
1093 |
|
}
|
1094 |
|
|
1095 |
|
// do we own it?
|
1096 |
|
for (Subject s: subjects) {
|
1097 |
|
logMetacat.debug("Comparing \t" +
|
1098 |
|
systemMetadata.getRightsHolder().getValue() +
|
1099 |
|
" \tagainst \t" + s.getValue());
|
1100 |
|
includedSubjects.append(s.getValue() + "; ");
|
1101 |
|
allowed = systemMetadata.getRightsHolder().equals(s);
|
1102 |
|
if (allowed) {
|
1103 |
|
return allowed;
|
1104 |
|
}
|
1105 |
|
}
|
1106 |
|
|
1107 |
|
// otherwise check the access rules
|
1108 |
|
try {
|
1109 |
|
List<AccessRule> allows = systemMetadata.getAccessPolicy().getAllowList();
|
1110 |
|
search: // label break
|
1111 |
|
for (AccessRule accessRule: allows) {
|
1112 |
|
for (Subject s: subjects) {
|
1113 |
|
logMetacat.debug("Checking allow access rule for subject: " + s.getValue());
|
1114 |
|
if (accessRule.getSubjectList().contains(s)) {
|
1115 |
|
logMetacat.debug("Access rule contains subject: " + s.getValue());
|
1116 |
|
for (Permission p: accessRule.getPermissionList()) {
|
1117 |
|
logMetacat.debug("Checking permission: " + p.xmlValue());
|
1118 |
|
expandedPermissions = expandPermissions(p);
|
1119 |
|
allowed = expandedPermissions.contains(permission);
|
1120 |
|
if (allowed) {
|
1121 |
|
logMetacat.info("Permission granted: " + p.xmlValue() + " to " + s.getValue());
|
1122 |
|
break search; //label break
|
1123 |
|
}
|
1124 |
|
}
|
1125 |
|
|
1126 |
|
}
|
1127 |
|
}
|
1128 |
|
}
|
1129 |
|
} catch (Exception e) {
|
1130 |
|
// catch all for errors - safe side should be to deny the access
|
1131 |
|
logMetacat.error("Problem checking authorization - defaulting to deny", e);
|
1132 |
|
allowed = false;
|
1133 |
|
|
1134 |
|
}
|
1135 |
|
|
1136 |
1064 |
// throw or return?
|
1137 |
1065 |
if (!allowed) {
|
1138 |
|
throw new NotAuthorized("1820", permission + " not allowed on " + pidStr + " for subject[s]: " + includedSubjects.toString() );
|
|
1066 |
// track the identities we have checked against
|
|
1067 |
StringBuffer includedSubjects = new StringBuffer();
|
|
1068 |
Set<Subject> subjects = AuthUtils.authorizedClientSubjects(session);
|
|
1069 |
for (Subject s: subjects) {
|
|
1070 |
includedSubjects.append(s.getValue() + "; ");
|
|
1071 |
}
|
|
1072 |
throw new NotAuthorized("1820", permission + " not allowed on " + pid.getValue() + " for subject[s]: " + includedSubjects.toString() );
|
1139 |
1073 |
}
|
1140 |
1074 |
|
1141 |
1075 |
return allowed;
|
1142 |
1076 |
|
1143 |
1077 |
}
|
1144 |
1078 |
|
|
1079 |
|
1145 |
1080 |
/*
|
|
1081 |
* Determine if a user has the permission to perform the specified permission.
|
|
1082 |
* 1. Owner can have any permission.
|
|
1083 |
* 2. Access table allow the user has the permission
|
|
1084 |
*/
|
|
1085 |
protected boolean userHasPermission(Session userSession, Identifier pid, Permission permission ) throws NotFound{
|
|
1086 |
boolean allowed = false;
|
|
1087 |
// permissions are hierarchical
|
|
1088 |
List<Permission> expandedPermissions = null;
|
|
1089 |
// get the subject[s] from the session
|
|
1090 |
//defer to the shared util for recursively compiling the subjects
|
|
1091 |
Set<Subject> subjects = AuthUtils.authorizedClientSubjects(userSession);
|
|
1092 |
|
|
1093 |
// get the system metadata
|
|
1094 |
String pidStr = pid.getValue();
|
|
1095 |
SystemMetadata systemMetadata = null;
|
|
1096 |
try {
|
|
1097 |
systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
|
|
1098 |
|
|
1099 |
} catch (Exception e) {
|
|
1100 |
// convert Hazelcast RuntimeException to NotFound
|
|
1101 |
logMetacat.error("An error occurred while getting system metadata for identifier " +
|
|
1102 |
pid.getValue() + ". The error message was: " + e.getMessage());
|
|
1103 |
throw new NotFound("1800", "No record found for " + pidStr);
|
|
1104 |
|
|
1105 |
}
|
|
1106 |
|
|
1107 |
// throw not found if it was not found
|
|
1108 |
if (systemMetadata == null) {
|
|
1109 |
String localId = null;
|
|
1110 |
String error = "No system metadata could be found for given PID: " + pidStr;
|
|
1111 |
try {
|
|
1112 |
localId = IdentifierManager.getInstance().getLocalId(pid.getValue());
|
|
1113 |
|
|
1114 |
} catch (Exception e) {
|
|
1115 |
logMetacat.warn("Couldn't find the local id for the pid "+pidStr);
|
|
1116 |
}
|
|
1117 |
|
|
1118 |
if(localId != null && EventLog.getInstance().isDeleted(localId)) {
|
|
1119 |
error = error + ". "+DELETEDMESSAGE;
|
|
1120 |
} else if (localId == null && EventLog.getInstance().isDeleted(pid.getValue())) {
|
|
1121 |
error = error + ". "+DELETEDMESSAGE;
|
|
1122 |
}
|
|
1123 |
throw new NotFound("1800", error);
|
|
1124 |
}
|
|
1125 |
|
|
1126 |
// do we own it?
|
|
1127 |
for (Subject s: subjects) {
|
|
1128 |
logMetacat.debug("Comparing \t" +
|
|
1129 |
systemMetadata.getRightsHolder().getValue() +
|
|
1130 |
" \tagainst \t" + s.getValue());
|
|
1131 |
//includedSubjects.append(s.getValue() + "; ");
|
|
1132 |
allowed = systemMetadata.getRightsHolder().equals(s);
|
|
1133 |
if (allowed) {
|
|
1134 |
return allowed;
|
|
1135 |
}
|
|
1136 |
}
|
|
1137 |
|
|
1138 |
// otherwise check the access rules
|
|
1139 |
try {
|
|
1140 |
List<AccessRule> allows = systemMetadata.getAccessPolicy().getAllowList();
|
|
1141 |
search: // label break
|
|
1142 |
for (AccessRule accessRule: allows) {
|
|
1143 |
for (Subject s: subjects) {
|
|
1144 |
logMetacat.debug("Checking allow access rule for subject: " + s.getValue());
|
|
1145 |
if (accessRule.getSubjectList().contains(s)) {
|
|
1146 |
logMetacat.debug("Access rule contains subject: " + s.getValue());
|
|
1147 |
for (Permission p: accessRule.getPermissionList()) {
|
|
1148 |
logMetacat.debug("Checking permission: " + p.xmlValue());
|
|
1149 |
expandedPermissions = expandPermissions(p);
|
|
1150 |
allowed = expandedPermissions.contains(permission);
|
|
1151 |
if (allowed) {
|
|
1152 |
logMetacat.info("Permission granted: " + p.xmlValue() + " to " + s.getValue());
|
|
1153 |
break search; //label break
|
|
1154 |
}
|
|
1155 |
}
|
|
1156 |
|
|
1157 |
}
|
|
1158 |
}
|
|
1159 |
}
|
|
1160 |
} catch (Exception e) {
|
|
1161 |
// catch all for errors - safe side should be to deny the access
|
|
1162 |
logMetacat.error("Problem checking authorization - defaulting to deny", e);
|
|
1163 |
allowed = false;
|
|
1164 |
|
|
1165 |
}
|
|
1166 |
return allowed;
|
|
1167 |
}
|
|
1168 |
/*
|
1146 |
1169 |
* parse a logEntry and get the relevant field from it
|
1147 |
1170 |
*
|
1148 |
1171 |
* @param fieldname
|
... | ... | |
1514 |
1537 |
|
1515 |
1538 |
}
|
1516 |
1539 |
|
|
1540 |
/**
|
|
1541 |
* Update the system metadata of the specified pid
|
|
1542 |
* @param session - the identity of the client which calls the method
|
|
1543 |
* @param pid - the identifier of the object which will be updated
|
|
1544 |
* @param sysmeta - the new system metadata
|
|
1545 |
* @return
|
|
1546 |
* @throws NotImplemented
|
|
1547 |
* @throws NotAuthorized
|
|
1548 |
* @throws ServiceFailure
|
|
1549 |
* @throws InvalidRequest
|
|
1550 |
* @throws InvalidSystemMetadata
|
|
1551 |
* @throws InvalidToken
|
|
1552 |
*/
|
1517 |
1553 |
public boolean updateSystemMetadata(Session session, Identifier pid,
|
1518 |
1554 |
SystemMetadata sysmeta) throws NotImplemented, NotAuthorized,
|
1519 |
1555 |
ServiceFailure, InvalidRequest, InvalidSystemMetadata, InvalidToken {
|
1520 |
1556 |
|
1521 |
1557 |
// The lock to be used for this identifier
|
1522 |
1558 |
Lock lock = null;
|
1523 |
|
if(pid == null || pid.getValue() == null) {
|
1524 |
|
throw new InvalidRequest("4863", "Please specify the id in the updateSystemMetadata request ") ;
|
1525 |
|
}
|
1526 |
|
|
1527 |
|
// TODO: control who can call this?
|
1528 |
|
if (session == null) {
|
1529 |
|
//TODO: many of the thrown exceptions do not use the correct error codes
|
1530 |
|
//check these against the docs and correct them
|
1531 |
|
throw new NotAuthorized("4861", "No Session - could not authorize for updating system metadata." +
|
1532 |
|
" If you are not logged in, please do so and retry the request.");
|
1533 |
|
} else {
|
1534 |
|
try {
|
1535 |
|
boolean allow = isAuthorized(session, pid, Permission.CHANGE_PERMISSION);
|
1536 |
|
if(!allow) {
|
1537 |
|
throw new NotAuthorized("4861", "The client -"+ session.getSubject().getValue()+ "is not authorized for updating the system metadata of the object "+pid.getValue());
|
1538 |
|
}
|
1539 |
|
} catch (NotFound e) {
|
1540 |
|
throw new InvalidRequest("4863", "Can't determine if the client has the permission to update the system metacat of the object with id "+pid.getValue()+" since "+e.getDescription());
|
1541 |
|
}
|
1542 |
|
|
1543 |
|
}
|
1544 |
|
|
|
1559 |
|
1545 |
1560 |
// verify that guid == SystemMetadata.getIdentifier()
|
1546 |
1561 |
logMetacat.debug("Comparing guid|sysmeta_guid: " + pid.getValue() +
|
1547 |
1562 |
"|" + sysmeta.getIdentifier().getValue());
|
... | ... | |
1600 |
1615 |
return true;
|
1601 |
1616 |
}
|
1602 |
1617 |
|
1603 |
|
/*
|
1604 |
|
* Determine if the current node is the authoritative node for the given pid.
|
1605 |
|
*/
|
1606 |
|
protected boolean isAuthoritativeNode(Identifier pid) {
|
1607 |
|
boolean isAuthoritativeNode = false;
|
1608 |
|
if(pid != null && pid.getValue() != null) {
|
1609 |
|
SystemMetadata sys = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
|
1610 |
|
if(sys != null) {
|
1611 |
|
NodeReference node = sys.getAuthoritativeMemberNode();
|
1612 |
|
if(node != null) {
|
1613 |
|
String nodeValue = node.getValue();
|
1614 |
|
logMetacat.debug("The authoritative node for id "+pid.getValue()+" is "+nodeValue);
|
1615 |
|
//System.out.println("The authoritative node for id "+pid.getValue()+" is "+nodeValue);
|
1616 |
|
String currentNodeId = Settings.getConfiguration().getString("dataone.nodeId");
|
1617 |
|
logMetacat.debug("The node id in metacat.properties is "+currentNodeId);
|
1618 |
|
//System.out.println("The node id in metacat.properties is "+currentNodeId);
|
1619 |
|
if(currentNodeId != null && !currentNodeId.trim().equals("") && currentNodeId.equals(nodeValue)) {
|
1620 |
|
logMetacat.debug("They are matching");
|
1621 |
|
//System.out.println("They are matching");
|
1622 |
|
isAuthoritativeNode = true;
|
1623 |
|
}
|
1624 |
|
}
|
1625 |
|
}
|
1626 |
|
}
|
1627 |
|
return isAuthoritativeNode;
|
1628 |
|
}
|
1629 |
1618 |
|
1630 |
1619 |
/*
|
1631 |
1620 |
* Check if the newMeta modifies an immutable field.
|
Refactory the authorize methods on D1NodeService.
Add the check for whom can call mn.updatesystemMetadata.