Search in sources :

Example 1 with AuthorizationsListBase

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>
 * &lt;baseURL&gt;/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;
}
Also used : DatawaveUser(datawave.security.authorization.DatawaveUser) DatawavePrincipal(datawave.security.authorization.DatawavePrincipal) Principal(java.security.Principal) DatawavePrincipal(datawave.security.authorization.DatawavePrincipal) AuthorizationsListBase(datawave.user.AuthorizationsListBase) HashSet(java.util.HashSet) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET)

Example 2 with AuthorizationsListBase

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);
    }
}
Also used : CallbackHandler(javax.security.auth.callback.CallbackHandler) NameCallback(javax.security.auth.callback.NameCallback) LoginContext(javax.security.auth.login.LoginContext) ObjectCallback(org.jboss.security.auth.callback.ObjectCallback) KeyStore(java.security.KeyStore) X509Certificate(java.security.cert.X509Certificate) AuthorizationsListBase(datawave.user.AuthorizationsListBase) Schedule(javax.ejb.Schedule)

Aggregations

AuthorizationsListBase (datawave.user.AuthorizationsListBase)2 DatawavePrincipal (datawave.security.authorization.DatawavePrincipal)1 DatawaveUser (datawave.security.authorization.DatawaveUser)1 KeyStore (java.security.KeyStore)1 Principal (java.security.Principal)1 X509Certificate (java.security.cert.X509Certificate)1 HashSet (java.util.HashSet)1 Schedule (javax.ejb.Schedule)1 CallbackHandler (javax.security.auth.callback.CallbackHandler)1 NameCallback (javax.security.auth.callback.NameCallback)1 LoginContext (javax.security.auth.login.LoginContext)1 GET (javax.ws.rs.GET)1 Path (javax.ws.rs.Path)1 Produces (javax.ws.rs.Produces)1 ObjectCallback (org.jboss.security.auth.callback.ObjectCallback)1