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}