// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.proxy;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Suppliers.memoizeWithExpiration;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.collect.ImmutableList;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
import google.registry.proxy.ProxyConfig.Environment;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMException;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
/**
* Dagger module that provides bindings needed to inject server certificate chain and private key.
*
*
The production certificates and private key are stored in a .pem file that is encrypted by
* Cloud KMS. The .pem file can be generated by concatenating the .crt certificate files on the
* chain and the .key private file.
*
*
The production certificates in the .pem file must be stored in order, where the next
* certificate's subject is the previous certificate's issuer.
*
*
When running the proxy locally or in test, a self signed certificate is used.
*
* @see Cloud Key Management Service
*/
@Module
public class CertificateModule {
/** Dagger qualifier to provide bindings related to the certificates that the server provides. */
@Qualifier
private @interface ServerCertificates {}
/** Dagger qualifier to provide bindings when running locally. */
@Qualifier
private @interface Local {}
/**
* Dagger qualifier to provide bindings when running in production.
*
*
The "production" here means that the proxy runs on GKE, as apposed to on a local machine. It
* does not necessary mean the production environment.
*/
@Qualifier
@interface Prod {}
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* Select specific type from a given {@link ImmutableList} and convert them using the converter.
*
* @param objects the {@link ImmutableList} to filter from.
* @param clazz the class to filter.
* @param converter the converter function to act on the items in the filtered list.
*/
private static ImmutableList filterAndConvert(
ImmutableList