001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2014 ForgeRock AS.
015 */
016
017package org.forgerock.openig.security;
018
019import static java.lang.String.*;
020import static org.forgerock.openig.util.Json.*;
021import static org.forgerock.util.Utils.*;
022
023import java.io.InputStream;
024import java.net.URL;
025import java.security.KeyStore;
026
027import org.forgerock.json.fluent.JsonValue;
028import org.forgerock.openig.heap.GenericHeaplet;
029import org.forgerock.openig.heap.HeapException;
030
031/**
032 * Represents a loaded Java {@link KeyStore}.
033 * <pre>
034 *     {
035 *         "name": "LocalKeyStore",
036 *         "type": "KeyStore",
037 *         "config": {
038 *             "url": "file://${env['HOME']}/keystore.jks",
039 *             "password": "secret",
040 *             "type": "JKS"
041 *         }
042 *     }
043 * </pre>
044 * <ul>
045 *     <li>{@literal url}: URL to the target key store file (expression, required).</li>
046 *     <li>{@literal type}: key store type (defaults to platform's default type) (string, optional).</li>
047 *     <li>{@literal password}: credential required to read private keys from the key store (expression, optional),
048 *     not needed when the key store is used for a trust store.</li>
049 * </ul>
050 * @since 3.1
051 */
052public class KeyStoreHeaplet extends GenericHeaplet {
053
054    @Override
055    public Object create() throws HeapException {
056        JsonValue urlString = config.get("url").required();
057        URL url = evaluateJsonStaticExpression(urlString).asURL();
058        String password = evaluate(config.get("password"));
059        String type = config.get("type").defaultTo(KeyStore.getDefaultType()).asString().toUpperCase();
060
061        KeyStore keyStore = null;
062        InputStream keyInput = null;
063        try {
064            keyStore = KeyStore.getInstance(type);
065            keyInput = url.openStream();
066            char[] credentials = (password == null) ? null : password.toCharArray();
067            keyStore.load(keyInput, credentials);
068        } catch (Exception e) {
069            throw new HeapException(format("Cannot load %S KeyStore from %s", type, urlString.asString()), e);
070        } finally {
071            closeSilently(keyInput);
072        }
073        return keyStore;
074    }
075}