Skip to content

Commit 161c501

Browse files
Add possibility to reload secrets from properties file with JCasC reload (#1556)
1 parent 9a40a90 commit 161c501

File tree

2 files changed

+57
-22
lines changed

2 files changed

+57
-22
lines changed

integrations/src/test/java/io/jenkins/plugins/casc/PropertiesSecretSourceTest.java

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
55
import io.jenkins.plugins.casc.misc.ConfiguredWithCode;
66
import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule;
7+
import java.io.File;
8+
import java.io.FileInputStream;
9+
import java.io.FileWriter;
10+
import java.io.InputStream;
711
import java.util.Collections;
812
import java.util.List;
13+
import java.util.Properties;
914
import jenkins.model.Jenkins;
1015
import org.junit.Rule;
1116
import org.junit.Test;
@@ -16,14 +21,16 @@
1621

1722
public class PropertiesSecretSourceTest {
1823

24+
private static final String USERNAME_SECRET = "ken";
25+
1926
@Rule
2027
public RuleChain chain = RuleChain.outerRule(new EnvironmentVariables()
2128
.set("SECRETS_FILE", getClass().getResource("secrets.properties").getFile()))
2229
.around(new JenkinsConfiguredWithCodeRule());
2330

2431
@Test
2532
@ConfiguredWithCode("PropertiesSecretSourceTest.yaml")
26-
public void test_reading_secrets_from_properties() throws Exception {
33+
public void testReadingSecretsFromProperties() throws Exception {
2734
List<UsernamePasswordCredentials> credentialList = CredentialsProvider
2835
.lookupCredentials(UsernamePasswordCredentials.class,
2936
Jenkins.getInstanceOrNull(), null, Collections.emptyList());
@@ -32,7 +39,39 @@ public void test_reading_secrets_from_properties() throws Exception {
3239
UsernamePasswordCredentials credentials = credentialList.get(0);
3340

3441
// https://leahneukirchen.org/blog/archive/2019/10/ken-thompson-s-unix-password.html
35-
assertEquals("ken", credentials.getUsername());
42+
assertEquals(USERNAME_SECRET, credentials.getUsername());
3643
assertEquals("p/q2-q4!", credentials.getPassword().getPlainText());
3744
}
45+
46+
@Test
47+
@ConfiguredWithCode("PropertiesSecretSourceTest.yaml")
48+
public void testSecretsFromPropertiesAreUpdatedAfterReload() throws Exception {
49+
File secretsFile = new File(getClass().getResource("secrets.properties").getFile());
50+
Properties secrets = new Properties();
51+
InputStream inputStream = new FileInputStream(secretsFile);
52+
secrets.load(inputStream);
53+
54+
FileWriter fileWriter = new FileWriter(secretsFile);
55+
56+
String secretName = "testuser";
57+
String updatedTestUserSecret = "charmander";
58+
secrets.setProperty(secretName, updatedTestUserSecret);
59+
try {
60+
secrets.store(fileWriter, "store to properties file");
61+
62+
ConfigurationAsCode.get().configure(this.getClass().getResource("PropertiesSecretSourceTest.yaml").toString());
63+
64+
List<UsernamePasswordCredentials> credentialList = CredentialsProvider
65+
.lookupCredentials(UsernamePasswordCredentials.class,
66+
Jenkins.getInstanceOrNull(), null, Collections.emptyList());
67+
assertEquals(1, credentialList.size());
68+
69+
UsernamePasswordCredentials credentials = credentialList.get(0);
70+
71+
assertEquals(updatedTestUserSecret, credentials.getUsername());
72+
} finally {
73+
secrets.setProperty(secretName, USERNAME_SECRET);
74+
secrets.store(fileWriter, "store to properties file");
75+
}
76+
}
3877
}

plugin/src/main/java/io/jenkins/plugins/casc/impl/secrets/PropertiesSecretSource.java

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,26 @@ public class PropertiesSecretSource extends SecretSource {
3232
*/
3333
public static final String SECRETS_DEFAULT_PATH = "/run/secrets/secrets.properties";
3434

35-
private Properties secrets;
35+
private final Properties secrets = new Properties();
3636

3737
@Override
3838
public Optional<String> reveal(String secret) {
39-
// lazy initialization
40-
if (secrets == null) {
41-
secrets = new Properties();
42-
final String secretsEnv = System.getenv("SECRETS_FILE");
43-
final String secretsPath = secretsEnv == null ? SECRETS_DEFAULT_PATH : secretsEnv;
44-
final File secretsFile = new File(secretsPath);
45-
if (secretsFile.exists() && secretsFile.isFile()) {
46-
try (InputStream input = new FileInputStream(secretsFile)) {
47-
secrets.load(input);
48-
} catch (IOException ioe) {
49-
LOGGER.log(Level.WARNING,
50-
"Source properties file " + secretsPath + " could not be loaded", ioe);
51-
}
52-
}
53-
}
39+
return Optional.ofNullable(secrets.getProperty(secret));
40+
}
5441

55-
if (secrets.getProperty(secret) == null) {
56-
return Optional.empty();
57-
} else {
58-
return Optional.of(secrets.getProperty(secret));
42+
@Override
43+
public void init() {
44+
final String secretsEnv = System.getenv("SECRETS_FILE");
45+
final String secretsPath = secretsEnv == null ? SECRETS_DEFAULT_PATH : secretsEnv;
46+
final File secretsFile = new File(secretsPath);
47+
if (secretsFile.exists() && secretsFile.isFile()) {
48+
try (InputStream input = new FileInputStream(secretsFile)) {
49+
secrets.clear();
50+
secrets.load(input);
51+
} catch (IOException ioe) {
52+
LOGGER.log(Level.WARNING,
53+
"Source properties file " + secretsPath + " could not be loaded", ioe);
54+
}
5955
}
6056
}
6157
}

0 commit comments

Comments
 (0)