use of datawave.user.AuthorizationsListBase in project datawave by NationalSecurityAgency.
the class UserOperationsBean method listEffectiveAuthorizations.
/**
* Lists the "effective" Accumulo user authorizations for the calling user. These are authorizations that are returned by the authorization service
* (possibly mapped to different values, or additional values added for Accumulo compatibility) intersected with the authorizations of the user that is used
* to connect to Accumulo. The authorizations returned by the call can be passed to query calls in order to return the maximum amount of data the user is
* authorized to see. Or, authorizations can be removed from this list to downgrade a query.
* <p>
* <strong>WARNING:</strong> If this call is made by a server proxying for a user (and/or other servers) then the response will contain multiple
* authorizations lists--one per entity. It is up to the caller to decide how to combine them if they wish to present a list to the user for downgrading.
* Note that {@link AuthorizationsListBase#getAllAuths()}, due to recent changes, actually returns only the user's authorizations. That is, these are the
* authorizations for the calling or proxied entity that represents a human, otherwise, the calling entity's authorizations. This list is sufficient for use
* in downgrading, but it should be noted the list is not necessarily representative of data that will be returned from a query. When evaluating data for
* return to a called, the data is tested against every authorization set listed here, and it must pass all of them to be returned. Therefore, if the user
* has the authorization FOO, but one of the other proxied entities in the chain does not, no data with FOO will be returned even though
* listEffectiveAuthorizations indicates the user has that authorization.
* <p>
* An example scenario where this comes into play is an external person querying through an internal server. The external party will have an authorization
* for their organization, say EXT1 for example, whereas the server will have the INT authorization. We want to be able to return data with releasabilities
* such as {@code INT&EXT1}, {@code INT&ALL_EXT}, but not data such as {@code INT&EXT2}. There is no single merged list of authorizations that will allow
* the correct data to come back. So, instead we test all data against each authorization set. For the {@code INT&EXT2} data example, the server's
* authorizations will allow the data to be returned since the server has INT. The user's authorizations will not allow the data to be returned however
* since the user has neither INT nor EXT2. In this scenario, the result for {@link AuthorizationsListBase#getAllAuths()} will contain both INT and EXT1
* even though the user does not have INT. The INT auth must be passed when queries are created, else no data would be returned (since the INT auth would be
* removed from the server's auths and then no data would be returned).
* <p>
* For most use cases, a GUI can compute the intersection of all authorizations that are not domains and then include the union of organizations. This will
* not always be the case, however. Consider data marked with something like: {@code FOO&INT|FOO&EXT}. If a system needs to support querying data such as
* that, then a simple intersection of everything except organization will no longer work.
* <p>
* Note that the the return type can be changed by specifying an Accept header, or by adding a suffix to the request URL. The following suffix to return
* type mppings are:
* <ul>
* <li>txt: text/plain
* <li>xml: application/xml
* <li>json: application/json
* </ul>
* For example, the URL
*
* <pre>
* <baseURL>/User/listEffectiveAuthorizations.json
* </pre>
*
* will return the results in JSON format.
*
* @return the user and proxied entities' authorizations
*/
@GET
@Path("/listEffectiveAuthorizations")
@Produces({ "application/xml", "text/xml", "text/plain", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "text/html" })
public AuthorizationsListBase listEffectiveAuthorizations() {
final AuthorizationsListBase list = responseObjectFactory.getAuthorizationsList();
// Find out who/what called this method
Principal p = context.getCallerPrincipal();
String name = p.getName();
if (p instanceof DatawavePrincipal) {
DatawavePrincipal datawavePrincipal = (DatawavePrincipal) p;
name = datawavePrincipal.getShortName();
// Add the user DN's auths into the authorization list
DatawaveUser primaryUser = datawavePrincipal.getPrimaryUser();
list.setUserAuths(primaryUser.getDn().subjectDN(), primaryUser.getDn().issuerDN(), new HashSet<>(primaryUser.getAuths()));
// Now add all entity auth sets into the list
datawavePrincipal.getProxiedUsers().forEach(u -> list.addAuths(u.getDn().subjectDN(), u.getDn().issuerDN(), new HashSet<>(u.getAuths())));
// Add the role to authorization mapping.
// NOTE: Currently this is only added for the primary user, which is really all anyone should care about in terms of mucking with
// authorizations. When used for queries, all non-primary users have all of their auths included -- there is no downgrading.
list.setAuthMapping(datawavePrincipal.getPrimaryUser().getRoleToAuthMapping().asMap());
}
log.trace(name + " has authorizations union " + list.getAllAuths());
return list;
}
use of datawave.user.AuthorizationsListBase in project datawave by NationalSecurityAgency.
the class ClientLoginExampleBean method doScheduledEvent.
@Schedule(hour = "*", minute = "*", second = "0", persistent = false)
public void doScheduledEvent() {
try {
// Grab the server certificate from the keystore (we are assuming it is the first one).
// This is the credential we'll set on the object callback.
KeyStore keystore = domain.getKeyStore();
final X509Certificate cert = (X509Certificate) keystore.getCertificate(keystore.aliases().nextElement());
// Compute the username. This would either be just a user DN if you are using a user's client
// certificate, or a server DN combined with a proxied user DN as we demonstrate here.
// Normally a username would go here. Hack for local testing--query the sid running jboss.
String userDN = System.getenv("USER_DN");
// We need the issuer of the user's cert. This needs to be set in the environment for this test.
String userIssuerDN = System.getenv("ISSUER_DN");
String serverDN = cert.getSubjectX500Principal().getName();
String serverIssuerDN = cert.getIssuerX500Principal().getName();
final String dn = DnUtils.buildNormalizedProxyDN(serverDN, serverIssuerDN, userDN, userIssuerDN);
// Handle the callback for authentication. We expect two callbacks, a NameCallback and an ObjectCallback.
CallbackHandler cbh = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) {
NameCallback nc = (NameCallback) callbacks[0];
ObjectCallback oc = (ObjectCallback) callbacks[1];
nc.setName(dn);
oc.setCredential(cert);
}
};
// Authenticate to the DATAWAVE client domain. This saves the credentials
// we passed in the callback handler above, and passes them along to the server
// when we attempt any calls that require a login on the server.
LoginContext lc = new LoginContext("datawave-client", cbh);
lc.login();
// Call secured EJBs
try {
AuthorizationsListBase auths = userOps.listEffectiveAuthorizations();
System.err.println("***** Auths for user " + dn + " are: " + auths);
} finally {
// Logout, which will restore previous credentials, if any.
// Be sure to do this in a finally block.
lc.logout();
}
} catch (Exception e) {
System.err.println("Error doing login!");
e.printStackTrace(System.err);
}
}
Aggregations