Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Merge pull request #46 from jenkinsci/JENKINS-37778
[JENKINS-37778] Support credentials in environment
- Loading branch information
Showing
with
975 additions
and 86 deletions.
- +6 −1 pipeline-model-definition/pom.xml
- +12 −1 ...model-definition/src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/Root.groovy
- +15 −1 ...odel-definition/src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/Stage.groovy
- +215 −0 ...src/main/java/org/jenkinsci/plugins/pipeline/modeldefinition/model/CredentialsBindingHandler.java
- +80 −0 ...inition/src/main/java/org/jenkinsci/plugins/pipeline/modeldefinition/steps/CredentialWrapper.java
- +2 −1 ...n/src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ClosureModelTranslator.groovy
- +106 −78 ...inition/src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy
- +27 −3 ...rc/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/PropertiesToMapTranslator.groovy
- +34 −0 ...definition/src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AbstractModelDefTest.java
- +1 −1 ...odel-definition/src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/EnvironmentTest.java
- +134 −0 ...src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/steps/CredentialWrapperStepTest.java
- +123 −0 ...del-definition/src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/util/HasArchived.java
- +80 −0 ...rc/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/util/InputStreamContainingString.java
- +50 −0 pipeline-model-definition/src/test/resources/credentials/mixedEnv.groovy
- +40 −0 pipeline-model-definition/src/test/resources/credentials/noBinding.groovy
- +50 −0 pipeline-model-definition/src/test/resources/credentials/usernamePassword.groovy
@@ -0,0 +1,215 @@ | ||
/* | ||
* The MIT License | ||
* | ||
* Copyright (c) 2016, CloudBees, Inc. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
* | ||
*/ | ||
|
||
package org.jenkinsci.plugins.pipeline.modeldefinition.model; | ||
|
||
import com.cloudbees.plugins.credentials.CredentialsProvider; | ||
import com.cloudbees.plugins.credentials.common.IdCredentials; | ||
import com.cloudbees.plugins.credentials.common.StandardCredentials; | ||
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials; | ||
import hudson.Extension; | ||
import hudson.ExtensionList; | ||
import hudson.ExtensionPoint; | ||
import hudson.model.Run; | ||
import org.apache.commons.jexl.context.HashMapContext; | ||
import org.apache.commons.lang.ObjectUtils; | ||
import org.apache.commons.lang.StringUtils; | ||
import org.jenkinsci.plugins.credentialsbinding.impl.CredentialNotFoundException; | ||
import org.jenkinsci.plugins.credentialsbinding.impl.FileBinding; | ||
import org.jenkinsci.plugins.credentialsbinding.impl.StringBinding; | ||
import org.jenkinsci.plugins.credentialsbinding.impl.UsernamePasswordBinding; | ||
import org.jenkinsci.plugins.credentialsbinding.impl.UsernamePasswordMultiBinding; | ||
import org.jenkinsci.plugins.plaincredentials.FileCredentials; | ||
import org.jenkinsci.plugins.plaincredentials.StringCredentials; | ||
|
||
import javax.annotation.CheckForNull; | ||
import javax.annotation.Nonnull; | ||
import java.io.Serializable; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
/** | ||
* Simplified {@link org.jenkinsci.plugins.credentialsbinding.Binding} handler for use in {@code environment {} } | ||
*/ | ||
public abstract class CredentialsBindingHandler implements ExtensionPoint { | ||
|
||
public boolean handles(Class<? extends StandardCredentials> c) { | ||
return type().isAssignableFrom(c); | ||
} | ||
|
||
public boolean handles(StandardCredentials c) { | ||
return handles(c.getClass()); | ||
} | ||
|
||
@Nonnull | ||
public abstract Class<? extends StandardCredentials> type(); | ||
|
||
@Nonnull | ||
public abstract List<Map<String, Object>> getWithCredentialsParameters(String credentialsId); | ||
|
||
@Nonnull | ||
public static ExtensionList<CredentialsBindingHandler> all() { | ||
return ExtensionList.lookup(CredentialsBindingHandler.class); | ||
} | ||
|
||
@Nonnull | ||
public static Set<Class<? extends StandardCredentials>> supportedTypes() { | ||
Set<Class<? extends StandardCredentials>> set = new HashSet<>(); | ||
for (CredentialsBindingHandler handler : all()) { | ||
set.add(handler.type()); | ||
} | ||
return set; | ||
} | ||
|
||
@Nonnull | ||
public static Set<String> supportedTypeNames() { | ||
Set<String> set = new HashSet<>(); | ||
for (Class<? extends StandardCredentials> c : supportedTypes()) { | ||
set.add(c.getSimpleName()); | ||
} | ||
return set; | ||
} | ||
|
||
@CheckForNull | ||
public static CredentialsBindingHandler forCredential(StandardCredentials c) { | ||
for (CredentialsBindingHandler handler : all()) { | ||
if (handler.handles(c)) { | ||
return handler; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
@Nonnull | ||
public static CredentialsBindingHandler forId(String id, Run context) throws CredentialNotFoundException { | ||
IdCredentials cred = CredentialsProvider.findCredentialById(id, IdCredentials.class, context); | ||
if (cred==null) { | ||
throw new CredentialNotFoundException(id); | ||
} | ||
if (cred instanceof StandardCredentials) { | ||
CredentialsBindingHandler handler = forCredential((StandardCredentials)cred); | ||
if (handler == null) { | ||
throw new CredentialNotFoundException(String.format("No suitable binding handler could be found for type %s. " + | ||
"Supported types are %s.", | ||
cred.getClass().getName(), | ||
StringUtils.join(supportedTypeNames(), ','))); | ||
} | ||
return handler; | ||
} else { | ||
throw new CredentialNotFoundException(String.format("Credentials %s is of type %s where " + | ||
"StandardCredentials is the expected type.", | ||
id, cred.getClass().getName())); | ||
} | ||
} | ||
|
||
public static class EnvVarResolver implements Serializable { | ||
private static final long serialVersionUID = 1L; | ||
|
||
private final String value; | ||
|
||
|
||
public EnvVarResolver() { | ||
this.value = "%s"; | ||
} | ||
|
||
public EnvVarResolver(String value) { | ||
this.value = value; | ||
} | ||
|
||
public String resolve(String varName) { | ||
return String.format(this.value, varName); | ||
} | ||
} | ||
|
||
@Extension | ||
public static class UsernamePasswordHandler extends CredentialsBindingHandler { | ||
|
||
@Override | ||
public Class<? extends StandardCredentials> type() { | ||
return StandardUsernamePasswordCredentials.class; | ||
} | ||
|
||
@Nonnull | ||
@Override | ||
public List<Map<String, Object>> getWithCredentialsParameters(String credentialsId) { | ||
Map<String, Object> map = new HashMap<>(); | ||
map.put("$class", UsernamePasswordBinding.class.getName()); | ||
map.put("variable", new EnvVarResolver()); | ||
map.put("credentialsId", credentialsId); | ||
Map<String, Object> map2 = new HashMap<>(); | ||
map2.put("$class", UsernamePasswordMultiBinding.class.getName()); | ||
map2.put("usernameVariable", new EnvVarResolver("%s_USR")); | ||
map2.put("passwordVariable", new EnvVarResolver("%s_PSW")); | ||
map2.put("credentialsId", credentialsId); | ||
return Arrays.asList(map, map2); | ||
} | ||
|
||
} | ||
|
||
@Extension | ||
public static class FileCredentialsHandler extends CredentialsBindingHandler { | ||
|
||
@Nonnull | ||
@Override | ||
public Class<? extends StandardCredentials> type() { | ||
return FileCredentials.class; | ||
} | ||
|
||
@Nonnull | ||
@Override | ||
public List<Map<String, Object>> getWithCredentialsParameters(String credentialsId) { | ||
Map<String, Object> map = new HashMap<>(); | ||
map.put("$class", FileBinding.class.getName()); | ||
map.put("variable", new EnvVarResolver()); | ||
map.put("credentialsId", credentialsId); | ||
return Collections.singletonList(map); | ||
} | ||
} | ||
|
||
@Extension | ||
public static class StringCredentialsHandler extends CredentialsBindingHandler { | ||
|
||
@Nonnull | ||
@Override | ||
public Class<? extends StandardCredentials> type() { | ||
return StringCredentials.class; | ||
} | ||
|
||
@Nonnull | ||
@Override | ||
public List<Map<String, Object>> getWithCredentialsParameters(String credentialsId) { | ||
Map<String, Object> map = new HashMap<>(); | ||
map.put("$class", StringBinding.class.getName()); | ||
map.put("variable", new EnvVarResolver()); | ||
map.put("credentialsId", credentialsId); | ||
return Collections.singletonList(map); | ||
} | ||
} | ||
} |
@@ -0,0 +1,80 @@ | ||
/* | ||
* The MIT License | ||
* | ||
* Copyright (c) 2016, CloudBees, Inc. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
* | ||
*/ | ||
|
||
package org.jenkinsci.plugins.pipeline.modeldefinition.steps; | ||
|
||
|
||
|
||
import org.jenkinsci.plugins.pipeline.modeldefinition.model.CredentialsBindingHandler; | ||
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted; | ||
|
||
import java.io.Serializable; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* Helper for simplified Credentials handling in {@code environment{}} | ||
*/ | ||
public class CredentialWrapper implements Serializable { | ||
private static final long serialVersionUID = 1L; | ||
|
||
private final String credentialId; | ||
private final List<Map<String, Object>> withCredentialsParameters; | ||
|
||
CredentialWrapper(String credentialId, List<Map<String, Object>> withCredentialsParameters) { | ||
this.withCredentialsParameters = withCredentialsParameters; | ||
this.credentialId = credentialId; | ||
} | ||
|
||
@Whitelisted | ||
public String getCredentialId() { | ||
return credentialId; | ||
} | ||
|
||
@Whitelisted | ||
public void addParameters(String envVarName, List<Map<String, Object>> list) { | ||
list.addAll(resolveParameters(envVarName)); | ||
} | ||
|
||
@Whitelisted | ||
public List<Map<String, Object>> resolveParameters(String envVarName) { | ||
List<Map<String, Object>> newList = new ArrayList<>(withCredentialsParameters.size()); | ||
for (Map<String, Object> params : withCredentialsParameters) { | ||
Map<String, Object> newP = new HashMap<>(); | ||
for (Map.Entry<String, Object> p : params.entrySet()) { | ||
Object value = p.getValue(); | ||
if (value instanceof CredentialsBindingHandler.EnvVarResolver) { | ||
newP.put(p.getKey(), ((CredentialsBindingHandler.EnvVarResolver)value).resolve(envVarName)); | ||
} else { | ||
newP.put(p.getKey(), p.getValue()); | ||
} | ||
} | ||
newList.add(newP); | ||
} | ||
return newList; | ||
} | ||
} |
Oops, something went wrong.