-
Notifications
You must be signed in to change notification settings - Fork 714
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
- Loading branch information
Showing
9 changed files
with
205 additions
and
3 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# credentials plugin | ||
|
||
## sample configuration | ||
|
||
```yaml | ||
credentials: | ||
system: | ||
? name: "test.com" | ||
description: "test.com domain" | ||
specifications: | ||
- hostnameSpecification: | ||
includes: | ||
- "*.test.com" | ||
: - usernamePassword: | ||
scope: SYSTEM | ||
id: sudo_password | ||
username: root | ||
password: 1234 | ||
? # "global" | ||
: - certificate: | ||
scope: SYSTEM | ||
id: ssh_private_key | ||
password: ABCD | ||
keyStoreSource: | ||
fileOnMaster: | ||
keyStoreFile: /docker/secret/id_rsa | ||
|
||
``` | ||
|
||
## implementation note | ||
|
||
credentials plugin support relies on a custom adaptor component `CredentialsRootConfigurator`. | ||
|
||
CredentialsStore uses as internal data model a `Map<Domain, List<Credentials>>`, so the yaml syntax (`? `) to define a | ||
complex mapping key. In previous sample, a Domain key is configured for `*.test.com` domain. | ||
|
||
Associated to this key, a list of credentials is defined based on hetero-describable symbol name (note the extra indent | ||
after `usernamePassword` This guy is a single entry map 'usernamePassword' => map of attributes to build target type). | ||
|
||
Credentials symbol name is inferred from implementation class simple name: `UsernamePasswordCredentialsImpl` | ||
descriptor's clazz is `Credentials` | ||
we consider the `Impl` suffix as a common pattern to flag implementation class. | ||
=> symbol name is `usernamePassword` | ||
|
||
|
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
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
67 changes: 67 additions & 0 deletions
67
src/main/java/org/jenkinsci/plugins/casc/credentials/CredentialsRootConfigurator.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,67 @@ | ||
package org.jenkinsci.plugins.casc.credentials; | ||
|
||
import com.cloudbees.plugins.credentials.Credentials; | ||
import com.cloudbees.plugins.credentials.CredentialsStore; | ||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider; | ||
import com.cloudbees.plugins.credentials.domains.Domain; | ||
import hudson.Extension; | ||
import org.jenkinsci.plugins.casc.Attribute; | ||
import org.jenkinsci.plugins.casc.Configurator; | ||
import org.jenkinsci.plugins.casc.RootElementConfigurator; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.logging.Logger; | ||
|
||
|
||
/** | ||
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a> | ||
*/ | ||
@Extension(optional = true) | ||
public class CredentialsRootConfigurator extends Configurator<CredentialsStore> implements RootElementConfigurator { | ||
|
||
private final static Logger logger = Logger.getLogger(CredentialsRootConfigurator.class.getName()); | ||
|
||
|
||
@Override | ||
public String getName() { | ||
return "credentials"; | ||
} | ||
|
||
@Override | ||
public Class<CredentialsStore> getTarget() { | ||
return CredentialsStore.class; | ||
} | ||
|
||
@Override | ||
public CredentialsStore configure(Object config) throws Exception { | ||
Map map = (Map) config; | ||
final Map<?,?> system = (Map) map.get("system"); | ||
final Map<Domain, List<Credentials>> target = SystemCredentialsProvider.getInstance().getDomainCredentialsMap(); | ||
target.clear(); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
ndeloof
Author
Contributor
|
||
|
||
final Configurator<Domain> domainConfigurator = Configurator.lookup(Domain.class); | ||
final Configurator<Credentials> credentialsConfigurator = Configurator.lookup(Credentials.class); | ||
|
||
for (Map.Entry dc : system.entrySet()) { | ||
final Domain domain = domainConfigurator.configure(dc.getKey()); | ||
List values = (List) dc.getValue(); | ||
final List<Credentials> credentials = new ArrayList<>(); | ||
for (Object value : values) { | ||
credentials.add(credentialsConfigurator.configure(value)); | ||
} | ||
logger.info("Setting "+target.getClass().getCanonicalName()+"#system["+domain.toString()+"] = " + credentials); | ||
target.put(domain, credentials); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Set<Attribute> describe() { | ||
return Collections.singleton(new Attribute("system", new HashMap<Domain, List<Credentials>>().getClass())); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
src/test/java/org/jenkinsci/plugins/casc/SystemCredentialsTest.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,46 @@ | ||
package org.jenkinsci.plugins.casc; | ||
|
||
import com.cloudbees.plugins.credentials.Credentials; | ||
import com.cloudbees.plugins.credentials.CredentialsProvider; | ||
import com.cloudbees.plugins.credentials.SystemCredentialsProvider; | ||
import com.cloudbees.plugins.credentials.common.CertificateCredentials; | ||
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials; | ||
import com.cloudbees.plugins.credentials.domains.Domain; | ||
import hudson.plugins.git.GitTool; | ||
import hudson.security.ACL; | ||
import jenkins.model.Jenkins; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.jvnet.hudson.test.JenkinsRule; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
/** | ||
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a> | ||
*/ | ||
public class SystemCredentialsTest { | ||
|
||
|
||
@Rule | ||
public JenkinsRule j = new JenkinsRule(); | ||
|
||
@Test | ||
public void configure_system_credentials() throws Exception { | ||
ConfigurationAsCode.configure(getClass().getResourceAsStream("SystemCredentialsTest.yml")); | ||
|
||
List<UsernamePasswordCredentials> ups = CredentialsProvider.lookupCredentials(UsernamePasswordCredentials.class, j.jenkins, ACL.SYSTEM, Collections.EMPTY_LIST); | ||
assertEquals(1, ups.size()); | ||
final UsernamePasswordCredentials up = ups.get(0); | ||
assertEquals("1234", up.getPassword().getPlainText()); | ||
|
||
List<CertificateCredentials> certs = CredentialsProvider.lookupCredentials(CertificateCredentials.class, j.jenkins, ACL.SYSTEM, Collections.EMPTY_LIST); | ||
assertEquals(1, certs.size()); | ||
final CertificateCredentials cert = certs.get(0); | ||
assertEquals("ABCD", cert.getPassword().getPlainText()); | ||
|
||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/test/resources/org/jenkinsci/plugins/casc/SystemCredentialsTest.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,22 @@ | ||
credentials: | ||
system: | ||
? name: "test.com" | ||
description: "test.com domain" | ||
specifications: | ||
- hostnameSpecification: | ||
includes: | ||
- "*.test.com" | ||
: - usernamePassword: | ||
scope: SYSTEM | ||
id: sudo_password | ||
username: root | ||
password: 1234 | ||
? # "global" | ||
: - certificate: | ||
scope: SYSTEM | ||
id: ssh_private_key | ||
password: ABCD | ||
keyStoreSource: | ||
fileOnMaster: | ||
keyStoreFile: /docker/secret/id_rsa | ||
|
@ndeloof doesn't this get called whenever the config-as-code changes?
if so this will cause intermittent build failures as credentials will go AWOL. whilst the credentials are re-populated?