org.dcache.gridsite.InMemoryCredentialStore.java Source code

Java tutorial

Introduction

Here is the source code for org.dcache.gridsite.InMemoryCredentialStore.java

Source

/* dCache - http://www.dcache.org/
 *
 * Copyright (C) 2014 Deutsches Elektronen-Synchrotron
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.dcache.gridsite;

import com.google.common.collect.Iterables;
import org.globus.gsi.gssapi.auth.AuthorizationException;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.springframework.beans.factory.annotation.Required;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import org.dcache.auth.util.GSSUtils;
import org.dcache.delegation.gridsite2.DelegationException;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.dcache.gridsite.Utilities.assertThat;

/**
 * An implementation of CredentialStore that holds credentials in-memory.
 * This is meant as a quick implementation to allow testing of the
 * infrastructure.  Real deployments will interface with SRM's existing
 * credential store.
 */
public class InMemoryCredentialStore implements CredentialStore {
    private Map<DelegationIdentity, GSSCredential> _storage = new HashMap<>();

    private String vomsDir;
    private String caDir;

    @Required
    public void setCaCertificatePath(String caDir) {
        this.caDir = caDir;
    }

    @Required
    public void setVomsdir(String vomsDir) {
        this.vomsDir = vomsDir;
    }

    @Override
    public GSSCredential get(DelegationIdentity id) throws DelegationException {
        GSSCredential credential = getAndCheckForExpired(id);
        assertThat(credential != null, "no credential", id);

        return credential;
    }

    // Simple wrapper that checks if the credential has expired
    private GSSCredential getAndCheckForExpired(DelegationIdentity id) {
        GSSCredential credential = _storage.get(id);

        if (credential != null && hasExpired(credential)) {
            _storage.remove(id);
            credential = null;
        }

        return credential;
    }

    @Override
    public void put(DelegationIdentity id, GSSCredential credential) {
        _storage.put(id, credential);
    }

    @Override
    public void remove(DelegationIdentity id) throws DelegationException {
        GSSCredential credential = _storage.remove(id);

        if (credential != null && hasExpired(credential)) {
            _storage.remove(id);
            credential = null;
        }

        assertThat(credential != null, "no credential", id);
    }

    @Override
    public boolean has(DelegationIdentity id) {
        return getAndCheckForExpired(id) != null;
    }

    @Override
    public Calendar getExpiry(DelegationIdentity id) throws DelegationException {
        GSSCredential credential = getAndCheckForExpired(id);
        assertThat(credential != null, "no credential", id);

        int remaining = remainingLifetimeOf(credential);

        if (remaining == GSSCredential.INDEFINITE_LIFETIME) {
            throw new DelegationException("credential has no expiry date");
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis() + SECONDS.toMillis(remaining));
        return calendar;
    }

    private static int remainingLifetimeOf(GSSCredential credential) {
        int remaining;

        try {
            remaining = credential.getRemainingLifetime();
        } catch (GSSException ignored) {
            remaining = 0; // Treat problematic credentials as having expired
        }

        return remaining;
    }

    private static boolean hasExpired(GSSCredential credential) {
        return remainingLifetimeOf(credential) == 0;
    }

    @Override
    public GSSCredential search(final String targetDn) {
        return bestCredentialMatching(new DnFqanMatcher() {
            @Override
            public boolean matches(String dn, String fqan) {
                return targetDn.equals(dn);
            }
        });
    }

    @Override
    public GSSCredential search(final String targetDn, final String targetFqan) {
        return bestCredentialMatching(new DnFqanMatcher() {
            @Override
            public boolean matches(String dn, String fqan) {
                return targetDn.equals(dn) && Objects.equals(targetFqan, fqan);
            }
        });
    }

    private interface DnFqanMatcher {
        public boolean matches(String dn, String fqan);
    }

    private GSSCredential bestCredentialMatching(DnFqanMatcher predicate) {
        GSSCredential bestCredential = null;
        long bestRemainingLifetime = 0;

        for (Map.Entry<DelegationIdentity, GSSCredential> entry : _storage.entrySet()) {
            try {
                GSSCredential credential = entry.getValue();
                Iterable<String> fqans = GSSUtils.getFQANsFromGSSCredential(vomsDir, caDir, credential);
                String primaryFqan = Iterables.getFirst(fqans, null);

                if (!predicate.matches(entry.getKey().getDn(), primaryFqan)) {
                    continue;
                }

                long remainingLifetime = credential.getRemainingLifetime();

                if (remainingLifetime > bestRemainingLifetime) {
                    bestRemainingLifetime = remainingLifetime;
                    bestCredential = credential;
                }
            } catch (GSSException | AuthorizationException ignored) {
                // Treat problematic credentials as having expired
            }
        }

        return bestCredential;
    }
}