-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for docker secrets (#509)
* Add simple docker compose service test * refactor * Parse secret and replace neo4j auth variable * Secrets override conf variables * Refactor * Refactor * Remove unused imports * Add secrets support for 4.4 * Apply script PR corrections * Fix TC tests * Move resource files to separate folder * Use waiting strategy * Fix 4.4 suffix check * Add logger * Add missing secret file test * Query config directly from database * Fix assertion to work for 5.x and 4.x * Test for secret file not being readable by docker * Refactor * Ignore test on ARM * Ignore all docker compose tests on ARM
- Loading branch information
Showing
8 changed files
with
284 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
173 changes: 173 additions & 0 deletions
173
src/test/java/com/neo4j/docker/TestDockerComposeSecrets.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package com.neo4j.docker; | ||
|
||
import com.neo4j.docker.coredb.configurations.Configuration; | ||
import com.neo4j.docker.coredb.configurations.Setting; | ||
import com.neo4j.docker.utils.DatabaseIO; | ||
import com.neo4j.docker.utils.TemporaryFolderManager; | ||
import com.neo4j.docker.utils.TestSettings; | ||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.Assumptions; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.testcontainers.containers.DockerComposeContainer; | ||
import org.testcontainers.containers.output.Slf4jLogConsumer; | ||
import org.testcontainers.containers.output.ToStringConsumer; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.nio.file.attribute.PosixFilePermissions; | ||
import java.time.Duration; | ||
|
||
import static com.neo4j.docker.utils.WaitStrategies.waitForBoltReady; | ||
|
||
public class TestDockerComposeSecrets | ||
{ | ||
private static final Logger log = LoggerFactory.getLogger( TestDockerComposeSecrets.class ); | ||
|
||
private static final int DEFAULT_BOLT_PORT = 7687; | ||
private static final int DEFAULT_HTTP_PORT = 7474; | ||
private static final Path TEST_RESOURCES_PATH = Paths.get( "src", "test", "resources", "dockersecrets" ); | ||
|
||
@RegisterExtension | ||
public static TemporaryFolderManager temporaryFolderManager = new TemporaryFolderManager(); | ||
|
||
@BeforeAll | ||
public static void skipTestsForARM() | ||
{ | ||
Assumptions.assumeFalse( System.getProperty( "os.arch" ).equals( "aarch64" ), | ||
"This test is ignored on ARM architecture, because Docker Compose Container doesn't support it." ); | ||
} | ||
|
||
private DockerComposeContainer createContainer( File composeFile, Path containerRootDir, String serviceName ) | ||
{ | ||
var container = new DockerComposeContainer( composeFile ); | ||
|
||
container.withExposedService( serviceName, DEFAULT_BOLT_PORT ) | ||
.withExposedService( serviceName, DEFAULT_HTTP_PORT ) | ||
.withEnv( "NEO4J_IMAGE", TestSettings.IMAGE_ID.asCanonicalNameString() ) | ||
.withEnv( "HOST_ROOT", containerRootDir.toAbsolutePath().toString() ) | ||
.waitingFor( serviceName, waitForBoltReady( Duration.ofSeconds( 90 ) ) ) | ||
.withLogConsumer( serviceName, new Slf4jLogConsumer( log ) ); | ||
|
||
return container; | ||
} | ||
|
||
@Test | ||
void shouldCreateContainerAndConnect() throws Exception | ||
{ | ||
var tmpDir = temporaryFolderManager.createFolder( "Simple_Container_Compose" ); | ||
var composeFile = copyDockerComposeResourceFile( tmpDir, TEST_RESOURCES_PATH.resolve( "simple-container-compose.yml" ).toFile() ); | ||
var serviceName = "simplecontainer"; | ||
|
||
try ( var dockerComposeContainer = createContainer( composeFile, tmpDir, serviceName ) ) | ||
{ | ||
dockerComposeContainer.start(); | ||
|
||
var dbio = new DatabaseIO( dockerComposeContainer.getServiceHost( serviceName, DEFAULT_BOLT_PORT ), | ||
dockerComposeContainer.getServicePort( serviceName, DEFAULT_BOLT_PORT ) ); | ||
dbio.verifyConnectivity( "neo4j", "simplecontainerpassword" ); | ||
} | ||
} | ||
|
||
@Test | ||
void shouldCreateContainerWithSecretPasswordAndConnect() throws Exception | ||
{ | ||
var tmpDir = temporaryFolderManager.createFolder( "Container_Compose_With_Secrets" ); | ||
var composeFile = copyDockerComposeResourceFile( tmpDir, TEST_RESOURCES_PATH.resolve( "container-compose-with-secrets.yml" ).toFile() ); | ||
var serviceName = "secretscontainer"; | ||
|
||
var newSecretPassword = "neo4j/newSecretPassword"; | ||
Files.createFile( tmpDir.resolve( "neo4j_auth.txt" ) ); | ||
Files.writeString( tmpDir.resolve( "neo4j_auth.txt" ), newSecretPassword ); | ||
|
||
try ( var dockerComposeContainer = createContainer( composeFile, tmpDir, serviceName ) ) | ||
{ | ||
dockerComposeContainer.start(); | ||
var dbio = new DatabaseIO( dockerComposeContainer.getServiceHost( serviceName, DEFAULT_BOLT_PORT ), | ||
dockerComposeContainer.getServicePort( serviceName, DEFAULT_BOLT_PORT ) ); | ||
dbio.verifyConnectivity( "neo4j", "newSecretPassword" ); | ||
} | ||
} | ||
|
||
@Test | ||
void shouldOverrideVariableWithSecretValue() throws Exception | ||
{ | ||
var tmpDir = temporaryFolderManager.createFolder( "Container_Compose_With_Secrets_Override" ); | ||
Files.createDirectories( tmpDir.resolve( "neo4j" ).resolve( "config" ) ); | ||
|
||
var composeFile = copyDockerComposeResourceFile( tmpDir, TEST_RESOURCES_PATH.resolve( "container-compose-with-secrets-override.yml" ).toFile() ); | ||
var serviceName = "secretsoverridecontainer"; | ||
|
||
var newSecretPageCache = "50M"; | ||
Files.createFile( tmpDir.resolve( "neo4j_pagecache.txt" ) ); | ||
Files.writeString( tmpDir.resolve( "neo4j_pagecache.txt" ), newSecretPageCache ); | ||
|
||
try ( var dockerComposeContainer = createContainer( composeFile, tmpDir, serviceName ) ) | ||
{ | ||
dockerComposeContainer.start(); | ||
|
||
var dbio = new DatabaseIO( dockerComposeContainer.getServiceHost( serviceName, DEFAULT_BOLT_PORT ), | ||
dockerComposeContainer.getServicePort( serviceName, DEFAULT_BOLT_PORT ) ); | ||
|
||
var secretSetting = dbio.getConfigurationSettingAsString( "neo4j", | ||
"secretsoverridecontainerpassword", | ||
Configuration.getConfigurationNameMap().get( Setting.MEMORY_PAGECACHE_SIZE ) ); | ||
|
||
Assertions.assertTrue( secretSetting.contains( "50" ) ); | ||
} | ||
} | ||
|
||
@Test | ||
void shouldFailIfSecretFileDoesNotExist() throws Exception | ||
{ | ||
var tmpDir = temporaryFolderManager.createFolder( "Container_Compose_With_Secrets_Override" ); | ||
var composeFile = copyDockerComposeResourceFile( tmpDir, TEST_RESOURCES_PATH.resolve( "container-compose-with-secrets-override.yml" ).toFile() ); | ||
var serviceName = "secretsoverridecontainer"; | ||
|
||
try ( var dockerComposeContainer = createContainer( composeFile, tmpDir, serviceName ) ) | ||
{ | ||
Assertions.assertThrows( Exception.class, dockerComposeContainer::start ); | ||
} | ||
} | ||
|
||
@Test | ||
void shouldFailAndPrintMessageIfFileIsNotReadable() throws Exception | ||
{ | ||
var tmpDir = temporaryFolderManager.createFolder( "Container_Compose_With_Secrets_Override" ); | ||
var composeFile = copyDockerComposeResourceFile( tmpDir, TEST_RESOURCES_PATH.resolve( "container-compose-with-secrets-override.yml" ).toFile() ); | ||
var serviceName = "secretsoverridecontainer"; | ||
|
||
Files.createFile( tmpDir.resolve( "neo4j_pagecache.txt" ) ); | ||
Files.writeString( tmpDir.resolve( "neo4j_pagecache.txt" ), "50M" ); | ||
|
||
var newPermissions = PosixFilePermissions.fromString( "rw-------" ); | ||
Files.setPosixFilePermissions( tmpDir.resolve( "neo4j_pagecache.txt" ), newPermissions ); | ||
|
||
try ( var dockerComposeContainer = createContainer( composeFile, tmpDir, serviceName ) ) | ||
{ | ||
var containerLogConsumer = new ToStringConsumer(); | ||
dockerComposeContainer.withLogConsumer( serviceName, containerLogConsumer ); | ||
var expectedLogLine = "The secret file '/run/secrets/neo4j_dbms_memory_pagecache_size_file' does not exist or is not readable. " + | ||
"Make sure you have correctly configured docker secrets."; | ||
Assertions.assertThrows( Exception.class, dockerComposeContainer::start ); | ||
Assertions.assertTrue( containerLogConsumer.toUtf8String().contains( expectedLogLine ) ); | ||
} | ||
} | ||
|
||
private File copyDockerComposeResourceFile( Path targetDirectory, File resourceFile ) throws IOException | ||
{ | ||
File compose_file = new File( targetDirectory.toString(), resourceFile.getName() ); | ||
if ( compose_file.exists() ) | ||
{ | ||
Files.delete( compose_file.toPath() ); | ||
} | ||
Files.copy( resourceFile.toPath(), Paths.get( compose_file.getPath() ) ); | ||
return compose_file; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/test/resources/dockersecrets/container-compose-with-secrets-override.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
services: | ||
secretsoverridecontainer: | ||
image: ${NEO4J_IMAGE} | ||
environment: | ||
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes | ||
- NEO4J_dbms_memory_pagecache_size_FILE=/run/secrets/neo4j_dbms_memory_pagecache_size_file | ||
- NEO4J_dbms_memory_pagecache_size=10M | ||
- NEO4J_DEBUG=true | ||
- NEO4J_AUTH=neo4j/secretsoverridecontainerpassword | ||
volumes: | ||
- ${HOST_ROOT}/neo4j/logs:/logs | ||
secrets: | ||
- neo4j_dbms_memory_pagecache_size_file | ||
secrets: | ||
neo4j_dbms_memory_pagecache_size_file: | ||
file: ./neo4j_pagecache.txt |
15 changes: 15 additions & 0 deletions
15
src/test/resources/dockersecrets/container-compose-with-secrets.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
services: | ||
secretscontainer: | ||
image: ${NEO4J_IMAGE} | ||
environment: | ||
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes | ||
- NEO4J_AUTH_FILE=/run/secrets/neo4j_auth_file | ||
- NEO4J_DEBUG=true | ||
volumes: | ||
- ${HOST_ROOT}/neo4j/data:/data | ||
- ${HOST_ROOT}/neo4j/logs:/logs | ||
secrets: | ||
- neo4j_auth_file | ||
secrets: | ||
neo4j_auth_file: | ||
file: ./neo4j_auth.txt |
10 changes: 10 additions & 0 deletions
10
src/test/resources/dockersecrets/simple-container-compose.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
services: | ||
simplecontainer: | ||
image: ${NEO4J_IMAGE} | ||
environment: | ||
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes | ||
- NEO4J_AUTH=neo4j/simplecontainerpassword | ||
- NEO4J_DEBUG=true | ||
volumes: | ||
- ${HOST_ROOT}/neo4j/data:/data | ||
- ${HOST_ROOT}/neo4j/logs:/logs |