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