001/*
002 * (C) Copyright 2019 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.blob.s3;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.nio.file.Files;
024import java.nio.file.Paths;
025import java.security.PrivateKey;
026import java.security.spec.InvalidKeySpecException;
027import java.util.Map;
028
029import org.nuxeo.ecm.blob.CloudBlobStoreConfiguration;
030import org.nuxeo.runtime.api.Framework;
031
032import com.amazonaws.auth.PEM;
033import com.amazonaws.auth.RSA;
034import com.amazonaws.services.cloudfront.util.SignerUtils.Protocol;
035import com.amazonaws.util.IOUtils;
036
037/**
038 * CloudFront configuration.
039 *
040 * @since 11.1
041 */
042public class CloudFrontConfiguration extends CloudBlobStoreConfiguration {
043
044    public static final String CLOUDFRONT_ENABLED_PROPERTY = "cloudfront.enabled";
045
046    public static final String CLOUDFRONT_PRIVATE_KEY_PROPERTY = "cloudfront.privKey";
047
048    public static final String CLOUDFRONT_PRIVATE_KEY_ID_PROPERTY = "cloudfront.privKeyId";
049
050    public static final String CLOUDFRONT_DISTRIBUTION_DOMAIN_PROPERTY = "cloudfront.distribDomain";
051
052    public static final String CLOUDFRONT_PROTOCOL_PROPERTY = "cloudfront.protocol";
053
054    // framework property for bug workaround
055    public static final String CLOUDFRONT_ENABLE_ENCODING_FIX = "nuxeo.s3storage.cloudfront.fix.encoding";
056
057    public final boolean enabled;
058
059    public final String distributionDomain;
060
061    public final Protocol protocol;
062
063    public final PrivateKey privateKey;
064
065    public final String keyPairId;
066
067    public final boolean fixEncoding;
068
069    public CloudFrontConfiguration(String systemPropertyPrefix, Map<String, String> properties) throws IOException {
070        super(systemPropertyPrefix, properties);
071        enabled = getBooleanProperty(CLOUDFRONT_ENABLED_PROPERTY);
072        if (enabled) {
073            protocol = Protocol.valueOf(getProperty(CLOUDFRONT_PROTOCOL_PROPERTY, "https"));
074            distributionDomain = getProperty(CLOUDFRONT_DISTRIBUTION_DOMAIN_PROPERTY);
075            privateKey = getPrivateKey(getProperty(CLOUDFRONT_PRIVATE_KEY_PROPERTY));
076            keyPairId = getProperty(CLOUDFRONT_PRIVATE_KEY_ID_PROPERTY);
077            // framework property for CloudFront bug workaround
078            fixEncoding = Framework.isBooleanPropertyTrue(CLOUDFRONT_ENABLE_ENCODING_FIX);
079        } else {
080            protocol = null;
081            distributionDomain = null;
082            privateKey = null;
083            keyPairId = null;
084            fixEncoding = false;
085        }
086    }
087
088    protected PrivateKey getPrivateKey(String path) throws IOException {
089        if (path == null) {
090            return null;
091        }
092        try (InputStream in = Files.newInputStream(Paths.get(path))) {
093            if (path.toLowerCase().endsWith(".pem")) {
094                return PEM.readPrivateKey(in);
095            }
096            if (path.toLowerCase().endsWith(".der")) {
097                return RSA.privateKeyFromPKCS8(IOUtils.toByteArray(in));
098            }
099            throw new IllegalArgumentException("Unsupported file type");
100        } catch (InvalidKeySpecException | IllegalArgumentException e) {
101            throw new IOException("Invalid CloudFront private key: " + path, e);
102        }
103    }
104
105}