mirror of https://github.com/grpc/grpc-java.git
xds: remove unused SecretManager code based on separate TlsCertificate and CertificateValidationContext secrets (#6310)
This commit is contained in:
parent
13fad99549
commit
ed845991db
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import io.envoyproxy.envoy.api.v2.core.ConfigSource;
|
||||
import io.grpc.Internal;
|
||||
|
||||
/**
|
||||
* SecretManager to manage secrets. This is used by gRPC-xds to access secrets
|
||||
* and not part of the public API of gRPC
|
||||
*/
|
||||
// TODO(sanjaypujare): Lifecycle management for this manager and the {@link SecretProvider}s
|
||||
// to be implemented using an object-pool mechanism
|
||||
@Internal
|
||||
public final class SecretManager {
|
||||
|
||||
/**
|
||||
* Finds an existing SecretProvider or creates it if it doesn't exist.
|
||||
*
|
||||
* @param configSource from the SdsSecretConfig
|
||||
* @param name from the SdsSecretConfig
|
||||
* @return the SecretProvider
|
||||
*/
|
||||
public SecretProvider<TlsCertificateStore> findOrCreateTlsCertificateProvider(
|
||||
ConfigSource configSource, String name) {
|
||||
checkNotNull(configSource, "configSource");
|
||||
checkNotNull(name, "name");
|
||||
// for now we support only path/volume based secret provider
|
||||
if (configSource.getConfigSourceSpecifierCase()
|
||||
!= ConfigSource.ConfigSourceSpecifierCase.PATH) {
|
||||
throw new UnsupportedOperationException("Only file based secret supported");
|
||||
}
|
||||
return secretVolumeCertificateProviders.findOrCreate(configSource, name);
|
||||
}
|
||||
|
||||
private final TlsCertificateSecretProviderMap secretVolumeCertificateProviders =
|
||||
new TlsCertificateSecretProviderMap();
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import io.envoyproxy.envoy.api.v2.core.ConfigSource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* SecretProviderMap used by SecretManager to maintain certificateProviders.
|
||||
*
|
||||
* @param <T> Type of secret stored in this Map
|
||||
*/
|
||||
abstract class SecretProviderMap<T> {
|
||||
|
||||
private final Map<String, SecretProvider<T>> providers;
|
||||
|
||||
protected SecretProviderMap() {
|
||||
providers = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an existing SecretProvider or creates it if it doesn't exist.
|
||||
*
|
||||
* @param configSource source part of the SdsSecretConfig
|
||||
* @param name name of the SdsSecretConfig
|
||||
* @return SecrerProvider
|
||||
*/
|
||||
final synchronized SecretProvider<T> findOrCreate(
|
||||
ConfigSource configSource, String name) {
|
||||
checkNotNull(configSource, "configSource");
|
||||
checkNotNull(name, "name");
|
||||
|
||||
String mapKey = "" + configSource.hashCode() + "." + name;
|
||||
SecretProvider<T> provider = providers.get(mapKey);
|
||||
if (provider == null) {
|
||||
provider = create(configSource, name);
|
||||
providers.put(mapKey, provider);
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
|
||||
abstract SecretProvider<T> create(ConfigSource configSource, String name);
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import io.envoyproxy.envoy.api.v2.core.ConfigSource;
|
||||
|
||||
final class TlsCertificateSecretProviderMap extends SecretProviderMap<TlsCertificateStore> {
|
||||
|
||||
@Override
|
||||
SecretProvider<TlsCertificateStore> create(ConfigSource configSource, String name) {
|
||||
checkNotNull(configSource, "configSource");
|
||||
checkNotNull(name, "name");
|
||||
// for now we support only path/volume based secret provider
|
||||
if (configSource.getConfigSourceSpecifierCase()
|
||||
!= ConfigSource.ConfigSourceSpecifierCase.PATH) {
|
||||
throw new UnsupportedOperationException("Only file based secret supported");
|
||||
}
|
||||
return new TlsCertificateSecretVolumeSecretProvider(configSource.getPath(), name);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.protobuf.ByteString;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Implementation of a file based secret provider.
|
||||
*/
|
||||
final class TlsCertificateSecretVolumeSecretProvider
|
||||
implements SecretProvider<TlsCertificateStore> {
|
||||
|
||||
public static final String PEM = ".pem";
|
||||
public static final String CRT = ".crt";
|
||||
private static final Logger logger = Logger
|
||||
.getLogger(TlsCertificateSecretVolumeSecretProvider.class.getName());
|
||||
private final String path;
|
||||
|
||||
// for now mark it unused
|
||||
@SuppressWarnings("unused")
|
||||
private final String name;
|
||||
|
||||
TlsCertificateSecretVolumeSecretProvider(String path, String name) {
|
||||
this.path = checkNotNull(path, "path");
|
||||
this.name = checkNotNull(name, "name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCallback(final Callback<TlsCertificateStore> callback, Executor executor) {
|
||||
checkNotNull(callback, "callback");
|
||||
checkNotNull(executor, "executor");
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// as per the contract of this provider we will get the current on-disk
|
||||
// contents of the files
|
||||
try {
|
||||
TlsCertificateStore tlsCert = get();
|
||||
callback.updateSecret(tlsCert);
|
||||
} catch (ExecutionException e) {
|
||||
logger.log(
|
||||
Level.SEVERE,
|
||||
"RuntimeException from get()",
|
||||
e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current contents of the private key and cert file. Assume the key has
|
||||
* <literal>.pem</literal> extension and cert has <literal>.crt</literal> extension
|
||||
* (needs to match mounted secrets).
|
||||
*/
|
||||
@VisibleForTesting
|
||||
TlsCertificateStore get() throws ExecutionException {
|
||||
try {
|
||||
final FileInputStream pemStream = new FileInputStream(path + PEM);
|
||||
final FileInputStream crtStream = new FileInputStream(path + CRT);
|
||||
return new TlsCertificateStore(ByteString.readFrom(pemStream),
|
||||
ByteString.readFrom(crtStream));
|
||||
} catch (IOException e) {
|
||||
throw new ExecutionException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.envoyproxy.envoy.api.v2.auth.TlsCertificate;
|
||||
import io.envoyproxy.envoy.api.v2.core.DataSource;
|
||||
import io.grpc.Internal;
|
||||
|
||||
/**
|
||||
* TlsCertificate's PrivateKey and Certificate are extracted into ByteString's.
|
||||
* Used by the gRPC SSLContext/Protocol Negotiator and is internal.
|
||||
* See {@link SecretManager} for a note on lifecycle management.
|
||||
*/
|
||||
@Internal
|
||||
public final class TlsCertificateStore {
|
||||
|
||||
private final ByteString privateKey;
|
||||
private final ByteString certChain;
|
||||
|
||||
private static ByteString getByteStringFromDataSource(DataSource dataSource) {
|
||||
checkNotNull(dataSource);
|
||||
ByteString dataSourceByteString = null;
|
||||
if (dataSource.getSpecifierCase() == DataSource.SpecifierCase.INLINE_BYTES) {
|
||||
dataSourceByteString = dataSource.getInlineBytes();
|
||||
} else if (dataSource.getSpecifierCase() == DataSource.SpecifierCase.INLINE_STRING) {
|
||||
dataSourceByteString = dataSource.getInlineStringBytes();
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"dataSource of type " + dataSource.getSpecifierCase() + " not supported");
|
||||
}
|
||||
return dataSourceByteString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Store out of the TlsCertificate object of xDS.
|
||||
*
|
||||
* @param tlsCertificate TlsCertificate Object of xDS
|
||||
*/
|
||||
public TlsCertificateStore(TlsCertificate tlsCertificate) {
|
||||
this(
|
||||
getByteStringFromDataSource(checkNotNull(tlsCertificate).getPrivateKey()),
|
||||
getByteStringFromDataSource(tlsCertificate.getCertificateChain()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Store out of 2 streams for the 2 certs on disk.
|
||||
*
|
||||
* @param privateKeySteam stream representing private key on disk
|
||||
* @param certChain stream representing cert on disk
|
||||
*/
|
||||
public TlsCertificateStore(ByteString privateKeySteam, ByteString certChain) {
|
||||
checkNotNull(privateKeySteam);
|
||||
checkNotNull(certChain);
|
||||
this.privateKey = privateKeySteam;
|
||||
this.certChain = certChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for private key stream.
|
||||
*
|
||||
* @return inputStream representing private key
|
||||
*/
|
||||
public ByteString getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for cert key stream.
|
||||
*
|
||||
* @return inputStream representing cert
|
||||
*/
|
||||
public ByteString getCertChain() {
|
||||
return certChain;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import io.envoyproxy.envoy.api.v2.core.ApiConfigSource;
|
||||
import io.envoyproxy.envoy.api.v2.core.ConfigSource;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SecretManager}.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class SecretManagerTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void createTest() throws IOException, ExecutionException, InterruptedException {
|
||||
ConfigSource configSource = TlsCertificateSecretProviderMapTest
|
||||
.createFileAndConfigSource(temporaryFolder);
|
||||
|
||||
SecretManager secretManager = new SecretManager();
|
||||
SecretProvider<TlsCertificateStore> provider = secretManager
|
||||
.findOrCreateTlsCertificateProvider(configSource, "test");
|
||||
assertThat(provider).isNotNull();
|
||||
TlsCertificateStore tlsCertificateStore =
|
||||
TlsCertificateSecretProviderMapTest.getValueThruCallback(provider);
|
||||
assertThat(tlsCertificateStore).isNotNull();
|
||||
TlsCertificateStoreTest
|
||||
.verifyKeyAndCertsWithStrings(tlsCertificateStore, "pemContents", "crtContents");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unused")
|
||||
public void nonFilePathConfigSource() {
|
||||
ConfigSource configSource =
|
||||
ConfigSource.newBuilder()
|
||||
.setApiConfigSource(ApiConfigSource.newBuilder().build())
|
||||
.build();
|
||||
|
||||
//thrown.expect(UnsupportedOperationException.class);
|
||||
SecretManager secretManager = new SecretManager();
|
||||
try {
|
||||
SecretProvider<TlsCertificateStore> provider = secretManager
|
||||
.findOrCreateTlsCertificateProvider(configSource, "test");
|
||||
Assert.fail("no exception thrown");
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
assertThat(expected).hasMessageThat()
|
||||
.contains("Only file based secret supported");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import io.envoyproxy.envoy.api.v2.core.ApiConfigSource;
|
||||
import io.envoyproxy.envoy.api.v2.core.ConfigSource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TlsCertificateSecretProviderMap}.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class TlsCertificateSecretProviderMapTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
/**
|
||||
* Utility function for creation of test files in a temp folder.
|
||||
* Used in other classes
|
||||
*
|
||||
* @param temporaryFolder temporary folder to use
|
||||
* @return a config source representing the file based secret
|
||||
* @throws IOException represents IO exception
|
||||
*/
|
||||
static ConfigSource createFileAndConfigSource(TemporaryFolder temporaryFolder)
|
||||
throws IOException {
|
||||
File filePath = TlsCertificateSecretVolumeSecretProviderTest
|
||||
.createTestCertFiles(temporaryFolder);
|
||||
|
||||
return ConfigSource.newBuilder()
|
||||
.setPath(filePath.getPath())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the value thru directExecutore callback. Used by other classes.
|
||||
*/
|
||||
static TlsCertificateStore getValueThruCallback(SecretProvider<TlsCertificateStore> provider) {
|
||||
SslContextSecretVolumeSecretProviderTest.TestCallback<TlsCertificateStore> testCallback
|
||||
= new SslContextSecretVolumeSecretProviderTest.TestCallback<>();
|
||||
provider.addCallback(testCallback, MoreExecutors.directExecutor());
|
||||
return testCallback.updatedSecret;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTest() throws IOException, ExecutionException, InterruptedException {
|
||||
ConfigSource configSource = createFileAndConfigSource(temporaryFolder);
|
||||
TlsCertificateSecretProviderMap map = new TlsCertificateSecretProviderMap();
|
||||
SecretProvider<TlsCertificateStore> provider = map.findOrCreate(configSource, "test");
|
||||
assertThat(provider).isNotNull();
|
||||
TlsCertificateStore tlsCertificateStore = getValueThruCallback(provider);
|
||||
assertThat(tlsCertificateStore).isNotNull();
|
||||
TlsCertificateStoreTest
|
||||
.verifyKeyAndCertsWithStrings(tlsCertificateStore, "pemContents", "crtContents");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonFilePathConfigSource() {
|
||||
ConfigSource configSource =
|
||||
ConfigSource.newBuilder()
|
||||
.setApiConfigSource(ApiConfigSource.newBuilder().build())
|
||||
.build();
|
||||
|
||||
TlsCertificateSecretProviderMap map = new TlsCertificateSecretProviderMap();
|
||||
try {
|
||||
SecretProvider<TlsCertificateStore> unused = map.findOrCreate(configSource, "test");
|
||||
Assert.fail("no exception thrown");
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
assertThat(expected).hasMessageThat()
|
||||
.contains("Only file based secret supported");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TlsCertificateSecretVolumeSecretProvider}.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class TlsCertificateSecretVolumeSecretProviderTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
/**
|
||||
* Utility function for creation of test files in a temp folder.
|
||||
*
|
||||
* @param temporaryFolder temporary folder to use
|
||||
* @return a config source representing the file based secret
|
||||
* @throws IOException represents an IO exception
|
||||
*/
|
||||
static File createTestCertFiles(TemporaryFolder temporaryFolder) throws IOException {
|
||||
createATestCertFile(temporaryFolder, "mycert.pem", "pemContents");
|
||||
createATestCertFile(temporaryFolder, "mycert.crt", "crtContents");
|
||||
|
||||
return new File(temporaryFolder.getRoot(), "mycert");
|
||||
}
|
||||
|
||||
private static void createATestCertFile(
|
||||
TemporaryFolder temporaryFolder,
|
||||
String s,
|
||||
String pemContents) throws IOException {
|
||||
File pem = temporaryFolder.newFile(s);
|
||||
Writer pemFile = Files.newBufferedWriter(pem.toPath(), UTF_8);
|
||||
pemFile.write(pemContents);
|
||||
pemFile.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readBothFiles() throws IOException, ExecutionException, InterruptedException {
|
||||
File filePath = createTestCertFiles(temporaryFolder);
|
||||
TlsCertificateSecretVolumeSecretProvider provider =
|
||||
new TlsCertificateSecretVolumeSecretProvider(filePath.getPath(), "test");
|
||||
|
||||
TlsCertificateStore tlsCertificateStore = provider.get();
|
||||
assertThat(tlsCertificateStore).isNotNull();
|
||||
TlsCertificateStoreTest
|
||||
.verifyKeyAndCertsWithStrings(tlsCertificateStore, "pemContents", "crtContents");
|
||||
}
|
||||
|
||||
private boolean listenerRun;
|
||||
|
||||
@Test
|
||||
public void verifyCallbackExecuted()
|
||||
throws IOException, ExecutionException, InterruptedException {
|
||||
// with a valid file we should get a callback
|
||||
File filePath = createTestCertFiles(temporaryFolder);
|
||||
TlsCertificateSecretVolumeSecretProvider provider =
|
||||
new TlsCertificateSecretVolumeSecretProvider(filePath.getPath(), "test");
|
||||
|
||||
listenerRun = false;
|
||||
provider.addCallback(new SecretProvider.Callback<TlsCertificateStore>() {
|
||||
|
||||
@Override
|
||||
public void updateSecret(TlsCertificateStore secret) {
|
||||
listenerRun = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Throwable throwable) {
|
||||
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
assertThat(listenerRun).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readMissingFile() throws IOException, ExecutionException, InterruptedException {
|
||||
createATestCertFile(temporaryFolder, "mycert.pem", "pemContents");
|
||||
|
||||
// no crt file
|
||||
File filePath = new File(temporaryFolder.getRoot(), "mycert");
|
||||
TlsCertificateSecretVolumeSecretProvider provider =
|
||||
new TlsCertificateSecretVolumeSecretProvider(filePath.getPath(), "test");
|
||||
|
||||
try {
|
||||
provider.get();
|
||||
Assert.fail("no exception thrown");
|
||||
} catch (ExecutionException expected) {
|
||||
assertThat(expected.getCause()).isInstanceOf(FileNotFoundException.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyCallbackNotExecuted()
|
||||
throws IOException, ExecutionException, InterruptedException {
|
||||
// with an invalid file we should NOT get a callback
|
||||
|
||||
TlsCertificateSecretVolumeSecretProvider provider =
|
||||
new TlsCertificateSecretVolumeSecretProvider("/a/b/test", "test");
|
||||
|
||||
listenerRun = false;
|
||||
provider.addCallback(new SecretProvider.Callback<TlsCertificateStore>() {
|
||||
|
||||
@Override
|
||||
public void updateSecret(TlsCertificateStore secret) {
|
||||
listenerRun = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Throwable throwable) {
|
||||
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
assertThat(listenerRun).isFalse();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 The gRPC Authors
|
||||
*
|
||||
* 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 io.grpc.xds.sds;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.envoyproxy.envoy.api.v2.auth.TlsCertificate;
|
||||
import io.envoyproxy.envoy.api.v2.core.DataSource;
|
||||
import java.io.IOException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TlsCertificateStore}.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class TlsCertificateStoreTest {
|
||||
|
||||
static void verifyKeyAndCertsWithStrings(TlsCertificateStore tlsCertificateStore, String s1,
|
||||
String s2) throws IOException {
|
||||
verifyKeyAndCertsWithStrings(tlsCertificateStore.getPrivateKey(), s1);
|
||||
verifyKeyAndCertsWithStrings(tlsCertificateStore.getCertChain(), s2);
|
||||
}
|
||||
|
||||
private static void verifyKeyAndCertsWithStrings(ByteString byteString, String s)
|
||||
throws IOException {
|
||||
assertThat(byteString).isNotNull();
|
||||
assertThat(byteString.toStringUtf8()).isEqualTo(s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertFromTlsCertificateUsingString() throws IOException {
|
||||
DataSource privateKey =
|
||||
DataSource.newBuilder()
|
||||
.setInlineString("test-privateKey")
|
||||
.build();
|
||||
DataSource certChain =
|
||||
DataSource.newBuilder()
|
||||
.setInlineString("test-certChain")
|
||||
.build();
|
||||
|
||||
TlsCertificate tlsCertificate =
|
||||
TlsCertificate.newBuilder()
|
||||
.setPrivateKey(privateKey)
|
||||
.setCertificateChain(certChain)
|
||||
.build();
|
||||
|
||||
TlsCertificateStore tlsCertificateStore = new TlsCertificateStore(tlsCertificate);
|
||||
|
||||
verifyKeyAndCertsWithStrings(tlsCertificateStore, "test-privateKey", "test-certChain");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertFromTlsCertificateUsingBytes() throws IOException {
|
||||
byte[] privateKeyBytes = {1, 2, 3, 4};
|
||||
byte[] certChainBytes = {4, 3, 2, 1};
|
||||
|
||||
DataSource privateKey =
|
||||
DataSource.newBuilder()
|
||||
.setInlineBytes(ByteString.copyFrom(privateKeyBytes))
|
||||
.build();
|
||||
DataSource certChain =
|
||||
DataSource.newBuilder()
|
||||
.setInlineBytes(ByteString.copyFrom(certChainBytes))
|
||||
.build();
|
||||
|
||||
TlsCertificate tlsCertificate =
|
||||
TlsCertificate.newBuilder()
|
||||
.setPrivateKey(privateKey)
|
||||
.setCertificateChain(certChain)
|
||||
.build();
|
||||
|
||||
TlsCertificateStore tlsCertificateStore = new TlsCertificateStore(tlsCertificate);
|
||||
|
||||
ByteString privateKeyByteString = tlsCertificateStore.getPrivateKey();
|
||||
assertThat(privateKeyByteString).isNotNull();
|
||||
assertThat(privateKeyByteString.toByteArray()).isEqualTo(privateKeyBytes);
|
||||
|
||||
ByteString certChainByteString = tlsCertificateStore.getCertChain();
|
||||
assertThat(certChainByteString).isNotNull();
|
||||
assertThat(certChainByteString.toByteArray()).isEqualTo(certChainBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void privateKeyNotSet() {
|
||||
DataSource certChain =
|
||||
DataSource.newBuilder()
|
||||
.setInlineString("test-certChain")
|
||||
.build();
|
||||
TlsCertificate tlsCertificate =
|
||||
TlsCertificate.newBuilder()
|
||||
.setCertificateChain(certChain)
|
||||
.build();
|
||||
|
||||
try {
|
||||
new TlsCertificateStore(tlsCertificate);
|
||||
Assert.fail("no exception thrown");
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
assertThat(expected).hasMessageThat()
|
||||
.contains("dataSource of type SPECIFIER_NOT_SET not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void certChainNotSet() {
|
||||
DataSource privateKey =
|
||||
DataSource.newBuilder()
|
||||
.setInlineString("test-privateKey")
|
||||
.build();
|
||||
TlsCertificate tlsCertificate =
|
||||
TlsCertificate.newBuilder()
|
||||
.setPrivateKey(privateKey)
|
||||
.build();
|
||||
try {
|
||||
new TlsCertificateStore(tlsCertificate);
|
||||
Assert.fail("no exception thrown");
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
assertThat(expected).hasMessageThat()
|
||||
.contains("dataSource of type SPECIFIER_NOT_SET not supported");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue