Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-69606

Ability to whitelist steps in Jenkinsfiles while allowing all steps in global pipeline libraries

      We are attempting to block access to pipeline steps that we consider a security risk (e.g. the Kubernetes plugin steps) from user provided Jenkinsfiles, but allowing access to all the steps from global pipeline libraries. Ideally we would only allow access to steps within our global pipeline library.

      The only way we have come up with is to create StepListener extension. The extension uses reflection on the StepContext to check whether the step was executed via the Jenkinsfile or a global pipeline library.

      As I understand it, this is not considered good practice and may break in future.

      Is there some existing functionality to achieve what we need here or the possibility of extending the StepListener API to provide it?

       

          [JENKINS-69606] Ability to whitelist steps in Jenkinsfiles while allowing all steps in global pipeline libraries

          Sam Gleske added a comment - - edited

          This would be a useful open source plugin.  Adding on, I would also like to not even necessarily allow all Vars or shared library steps.  In some cases, I develop a global step meant only for private use in the global shared pipeline library.  Not meant for use by users.

          Detecting a global var

          Here's some code which allows a dynamic var look up to see if a step is a core Jenkins step or a shared pipeline var.

          https://github.com/samrocketman/jervis/blob/64d21aff1d08ae58cc310cae5e868a4923b4bcab/vars/hasGlobalVar.groovy#L33

          It would be great if the whitelist could also apply to global vars or have an option around global vars.

          Other necessary considerations

          I've found doing a basic AST review of a Jenkinsfile is not enough because a user can pull in a user shared library via the library step.  I think user shared libraries should be supported so allowing steps in a user shared library is useful to be automatically white listed without having to explicitly state allowed steps.

          This also means it is necessary for limitations around allowed steps also be applied to the contents of user shared libraries.

          Sam Gleske added a comment - - edited This would be a useful open source plugin.  Adding on, I would also like to not even necessarily allow all Vars or shared library steps.  In some cases, I develop a global step meant only for private use in the global shared pipeline library.  Not meant for use by users. Detecting a global var Here's some code which allows a dynamic var look up to see if a step is a core Jenkins step or a shared pipeline var. https://github.com/samrocketman/jervis/blob/64d21aff1d08ae58cc310cae5e868a4923b4bcab/vars/hasGlobalVar.groovy#L33 It would be great if the whitelist could also apply to global vars or have an option around global vars. Other necessary considerations I've found doing a basic AST review of a Jenkinsfile is not enough because a user can pull in a user shared library via the library step.  I think user shared libraries should be supported so allowing steps in a user shared library is useful to be automatically white listed without having to explicitly state allowed steps. This also means it is necessary for limitations around allowed steps also be applied to the contents of user shared libraries.

          Sam Gleske added a comment -

          Added script-security-plugin as a component.  This might be best a feature request in the script security plugin.  To enable a vars and steps allow or block list.

          Sam Gleske added a comment - Added script-security-plugin as a component.  This might be best a feature request in the script security plugin.  To enable a vars and steps allow or block list.

          Sam Gleske added a comment -

          mwinter69 shared with me some great resources from Gitter. I plan to implement and open source a plugin for this since this is a need I have.

          Potential extension points:

          Sam Gleske added a comment - mwinter69 shared with me some great resources from Gitter. I plan to implement and open source a plugin for this since this is a need I have. Potential extension points: https://javadoc.jenkins.io/plugin/workflow-api/org/jenkinsci/plugins/workflow/flow/GraphListener.html https://javadoc.jenkins.io/plugin/workflow-api/org/jenkinsci/plugins/workflow/flow/StepListener.html

          Sam Gleske added a comment -

          Another example, shell step https://github.com/jenkinsci/workflow-durable-task-step-plugin/blob/master/src/main/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStep.java has a getFunction call which returns "sh" on its descriptor impl.

          Here's an example of sandbox usage.

          https://github.com/jenkinsci/workflow-durable-task-step-plugin/pull/110/files#diff-d41f0e79c6665d69c24339f2d6671f9a4f7e1e0457638614cd48c0a6a44ae4cb

          https://javadoc.jenkins.io/plugin/workflow-cps/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.html CPS flow definition has isSandbox method. This could hypothetically be used to determine if a step was called by a global shared library or a user Jenkinsfile. Shared libraries are not sandboxed while user Jenkinsfiles are. I'll need to test more on this when I actually start implementing.

          Sam Gleske added a comment - Another example, shell step https://github.com/jenkinsci/workflow-durable-task-step-plugin/blob/master/src/main/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStep.java has a getFunction call which returns "sh" on its descriptor impl. Here's an example of sandbox usage. https://github.com/jenkinsci/workflow-durable-task-step-plugin/pull/110/files#diff-d41f0e79c6665d69c24339f2d6671f9a4f7e1e0457638614cd48c0a6a44ae4cb https://javadoc.jenkins.io/plugin/workflow-cps/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.html CPS flow definition has isSandbox method. This could hypothetically be used to determine if a step was called by a global shared library or a user Jenkinsfile. Shared libraries are not sandboxed while user Jenkinsfiles are. I'll need to test more on this when I actually start implementing.

          Sam Gleske added a comment - - edited

          Step implements getDescriptor so to get the step name via Groovy one would call ".descriptor.functionName"

          Sam Gleske added a comment - - edited Step implements getDescriptor so to get the step name via Groovy one would call ".descriptor.functionName"

          Sam Gleske added a comment -

          Sam Gleske added a comment - I have published a plugin https://github.com/samrocketman/restrict-steps-plugin and opened a hosting request https://github.com/jenkins-infra/repository-permissions-updater/issues/3391

          Sam Gleske added a comment -

          Global variables get invoked here. It would be nice if there was a Listener similar to StepListener to do some kind of pre-flight check before it is called.

          I also notice CpsWhitelist has it. Perhaps I could update the whitelist at runtime somehow to prevent users from calling the shared library steps.

          Currently, there's no easy way to determine if a step was called from a Global var (out of sandbox) or a user pipeline (in sandbox). I'm still researching.

          Sam Gleske added a comment - Global variables get invoked here . It would be nice if there was a Listener similar to StepListener to do some kind of pre-flight check before it is called. I also notice CpsWhitelist has it. Perhaps I could update the whitelist at runtime somehow to prevent users from calling the shared library steps. Currently, there's no easy way to determine if a step was called from a Global var (out of sandbox) or a user pipeline (in sandbox). I'm still researching.

          Sam Gleske added a comment -

          jglick what are your thoughts on supporting adding a forbiddenMethod in script security WhiteList with an abstract default to false? And then plugins like this one could implement the ExtensionPoint and reject steps and vars via script security? It would reduce runtime load by not having to snoop with StepListener (not that there's much) but the primary benefit is this way would cover vars and steps alike.

          https://github.com/jenkinsci/script-security-plugin/blob/bc3f03b64447fbb24f8380aca2598162499060f7/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/ProxyWhitelist.java#L193-L195

          Sam Gleske added a comment - jglick what are your thoughts on supporting adding a forbiddenMethod in script security WhiteList with an abstract default to false? And then plugins like this one could implement the ExtensionPoint and reject steps and vars via script security? It would reduce runtime load by not having to snoop with StepListener (not that there's much) but the primary benefit is this way would cover vars and steps alike. https://github.com/jenkinsci/script-security-plugin/blob/bc3f03b64447fbb24f8380aca2598162499060f7/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/ProxyWhitelist.java#L193-L195

          Sam Gleske added a comment - - edited

          I'm referring to "forbidden" equivalents to all methods in https://github.com/jenkinsci/script-security-plugin/blob/bc3f03b64447fbb24f8380aca2598162499060f7/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/Whitelist.java with abstract implementations to support backwards compatibility. i.e. nothing forbidden by default but a plugin like this one could override it.

          With forbidden taking precedence over permitted. i.e. an admin should be able to forbid anything regardless of built-in whitelisted syntax in the pipeline AST.

          Sam Gleske added a comment - - edited I'm referring to "forbidden" equivalents to all methods in https://github.com/jenkinsci/script-security-plugin/blob/bc3f03b64447fbb24f8380aca2598162499060f7/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/Whitelist.java with abstract implementations to support backwards compatibility. i.e. nothing forbidden by default but a plugin like this one could override it. With forbidden taking precedence over permitted. i.e. an admin should be able to forbid anything regardless of built-in whitelisted syntax in the pipeline AST.

          Sam Gleske added a comment -

          And potential implementation in ProxyWhitelist.java

          boolean permitted = false;
          boolean forbidden = false;
          for (Whitelist delegate : delegates) {
              if (delegate.permitsMethod(method, receiver, args)) {
                  permitted = true;
              }
              if (delegate.forbidsMethod(method, receiver, args)) {
                  forbidden = true;
              }
          }
          return (forbidden) ? false : permitted;
          
          

          Sam Gleske added a comment - And potential implementation in ProxyWhitelist.java boolean permitted = false ; boolean forbidden = false ; for (Whitelist delegate : delegates) { if (delegate.permitsMethod(method, receiver, args)) { permitted = true ; } if (delegate.forbidsMethod(method, receiver, args)) { forbidden = true ; } } return (forbidden) ? false : permitted;

          Jesse Glick added a comment -

          I do not recommend messing around with Whitelist. What is wrong with StepListener? It is designed for exactly this purpose.

          Jesse Glick added a comment - I do not recommend messing around with Whitelist . What is wrong with StepListener ? It is designed for exactly this purpose.

          Sam Gleske added a comment - - edited

          StepListener does not cover vars (neither built-in like "pipeline" var for model definition nor admin-provided global vars).

          Use case 1

          For example, I use scripted pipeline.  As part of maintaining ephemeral credentials (in a global pipeline var) we make calls to Amazon STS to provide 1 hour ephemeral AWS credentials via assume role.  I don't use access keys anywhere for AWS and everything is restricted to short-lived credentials.  For compliance tracking users don't interact with AWS credentials step directly and instead must go through another step.  I would like to be able to block users from calling some of the pipeline vars but allow others (for global shared libs I provide).

          Use case 2

          We also don't support pipeline model definition because we have specific ways on how an agent should be set up.  To DRY up code we have a generic buildAgent step and a stageWithAgent step.  New users who are familiar with Jenkins sometimes get confused when the try to use "pipeline {}" and it would be a better user experience if rather than it failing with a strange cryptic error that the get "blocked by admins" instead.

          Why not declarative?

          The short version is it falls far short of my company needs and I don't have the buy-in at work to do full-time Jenkins development.  I use scripted pipeline and some custom plugins that I wrote to fill the gaps but ideally I would like to contribute most of this work back upstream where possible through an agreement with my employer.  As of now, I don't have that.

          The experience is still decent for users.  The DSL I provide to users.

          pullRequestPipeline {
              stageWithAgent(name: 'My stage') {
                  runSh './.ci/script.sh'
              }
          }
          
          pullRequestAndTag {
              publishToNexus()
          }
          
          branchPipeline {
              createTagOnMergeTo(branch: 'master')
          }
          
          tagPipeline {
              deployStage(name: 'Some deploy', environment: 'dev') {
                  runSh './.ci/deploy.sh'
              }
              // and for staging and prod
          }
          

          Surrounding this code we add before and after required stages such as compliance checking, security scanning, and other purposes. We have custom plugins extending Jenkins for capturing our logs in a particular way we need for compliance. 

          Challenge

          Vars (and builtin vars like "pipeline {}" provided by declarative) are automatically approved in the Whitelist.  This makes sense.  However, when calling vars there's no step listener event fired because it's not a part of the FlowNodes in the Graph.  Instead, it is called directly via invoke and bypasses the graph entirely.

          https://github.com/jenkinsci/workflow-cps-plugin/blob/a9795f98880c8fab08a904c1620bdf27f96faa8b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsScript.java#L110-L120

          See also

          My desired end-state for this plugin in the Known Gaps section https://github.com/jenkinsci/restrict-steps-plugin/tree/b9ad73d82bb6af03d20f0e747f129e3652c4020f#known-gaps

          Workflow CPS does not currently provide the flexibility so it needs to be patched.  Either by Whitelist (for sandboxed which I think is most desirable since that runs only once) or invoke for global pipeline vars needs to notify StepListener.  This makes less sense to me because they aren't steps.

          Sam Gleske added a comment - - edited StepListener does not cover vars (neither built-in like "pipeline" var for model definition nor admin-provided global vars). Use case 1 For example, I use scripted pipeline.  As part of maintaining ephemeral credentials (in a global pipeline var) we make calls to Amazon STS to provide 1 hour ephemeral AWS credentials via assume role.  I don't use access keys anywhere for AWS and everything is restricted to short-lived credentials.  For compliance tracking users don't interact with AWS credentials step directly and instead must go through another step.  I would like to be able to block users from calling some of the pipeline vars but allow others (for global shared libs I provide). Use case 2 We also don't support pipeline model definition because we have specific ways on how an agent should be set up.  To DRY up code we have a generic buildAgent step and a stageWithAgent step.  New users who are familiar with Jenkins sometimes get confused when the try to use "pipeline {}" and it would be a better user experience if rather than it failing with a strange cryptic error that the get "blocked by admins" instead. Why not declarative? The short version is it falls far short of my company needs and I don't have the buy-in at work to do full-time Jenkins development.  I use scripted pipeline and some custom plugins that I wrote to fill the gaps but ideally I would like to contribute most of this work back upstream where possible through an agreement with my employer.  As of now, I don't have that. The experience is still decent for users.  The DSL I provide to users. pullRequestPipeline { stageWithAgent(name: 'My stage' ) { runSh './.ci/script.sh' } } pullRequestAndTag { publishToNexus() } branchPipeline { createTagOnMergeTo(branch: 'master' ) } tagPipeline { deployStage(name: 'Some deploy' , environment: 'dev' ) { runSh './.ci/deploy.sh' } // and for staging and prod } Surrounding this code we add before and after required stages such as compliance checking, security scanning, and other purposes. We have custom plugins extending Jenkins for capturing our logs in a particular way we need for compliance.  Challenge Vars (and builtin vars like "pipeline {}" provided by declarative) are automatically approved in the Whitelist.  This makes sense.  However, when calling vars there's no step listener event fired because it's not a part of the FlowNodes in the Graph.  Instead, it is called directly via invoke and bypasses the graph entirely. https://github.com/jenkinsci/workflow-cps-plugin/blob/a9795f98880c8fab08a904c1620bdf27f96faa8b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsScript.java#L110-L120 See also My desired end-state for this plugin in the Known Gaps section https://github.com/jenkinsci/restrict-steps-plugin/tree/b9ad73d82bb6af03d20f0e747f129e3652c4020f#known-gaps Workflow CPS does not currently provide the flexibility so it needs to be patched.  Either by Whitelist (for sandboxed which I think is most desirable since that runs only once) or invoke for global pipeline vars needs to notify StepListener.  This makes less sense to me because they aren't steps.

          Sam Gleske added a comment -

          Sam Gleske added a comment - This plugin is now hosted at https://github.com/jenkinsci/restrict-steps-plugin

          Jesse Glick added a comment -

          I think we could add a new method to StepListener for global variables.

          Jesse Glick added a comment - I think we could add a new method to StepListener for global variables.

          Sam Gleske added a comment -

          StepListener itself is currently lacking a few things. It makes a difference between a global shared libary calling a step (or var) and an end-user from sandboxed Jenkinsfile.

          Currently, if you block a step with StepListener it will block it for both users and global shared pipelines. This isn't really the desired result, though it does allow me to block some steps.

          Sam Gleske added a comment - StepListener itself is currently lacking a few things. It makes a difference between a global shared libary calling a step (or var) and an end-user from sandboxed Jenkinsfile. Currently, if you block a step with StepListener it will block it for both users and global shared pipelines. This isn't really the desired result, though it does allow me to block some steps.

          Sam Gleske added a comment -

          Any ideas for how to detect within StepListener if someone is calling that step from a non-sandboxed global lib as opposed to a sandboxed Jenkinsfile?

          Ideally, the admin libs wouldn't be blocked from using steps but end-user Jenkinsfiles would. The current implementation of restrict-steps-plugin even blocks global shared libs from calling those steps (it even blocks declarative).

          But ideally, optionally including admin vars and blocking only within the scope of the Jenkinsfile would be more desirable.

          Sam Gleske added a comment - Any ideas for how to detect within StepListener if someone is calling that step from a non-sandboxed global lib as opposed to a sandboxed Jenkinsfile? Ideally, the admin libs wouldn't be blocked from using steps but end-user Jenkinsfiles would. The current implementation of restrict-steps-plugin even blocks global shared libs from calling those steps (it even blocks declarative). But ideally, optionally including admin vars and blocking only within the scope of the Jenkinsfile would be more desirable.

          Sam Gleske added a comment -

          Can https://github.com/jenkinsci/script-security-plugin/blob/master/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SandboxInterceptor.java be extended to enable plugins to provide block lists? For example, a plugin blocking certain vars or steps.

          Sam Gleske added a comment - Can https://github.com/jenkinsci/script-security-plugin/blob/master/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SandboxInterceptor.java be extended to enable plugins to provide block lists? For example, a plugin blocking certain vars or steps.

          Jesse Glick added a comment -

          I doubt Pipeline can easily be made to enforce the sort of EDSL you describe. (Nor can I recommend JTE, which has serious design issues and makes use of Pipeline internals that are not guaranteed to be stable at all.) I would rather advise not offering Pipeline Groovy directly to users at all; instead load some list of requested “steps” for example from a YAML file, and essentially interpret it as a plain DSL.

          Jesse Glick added a comment - I doubt Pipeline can easily be made to enforce the sort of EDSL you describe. (Nor can I recommend JTE, which has serious design issues and makes use of Pipeline internals that are not guaranteed to be stable at all.) I would rather advise not offering Pipeline Groovy directly to users at all; instead load some list of requested “steps” for example from a YAML file, and essentially interpret it as a plain DSL.

          Sam Gleske added a comment -

          To clarify, I'm not trying to enforce the DSL and am fine with users making use of most of the Jenkins steps.

          There's a few vars which pose issues if users use them directly due to what they do in the runtime and are only meant for reuse in other vars. Currently Jenkins doesn't have a concept of private vars which is essentially what I want.

          The other idea was to rely on sandbox to prevent var usage but it doesn't have the infrastructure set up in it. I've considered a YAML only spec but there's a lot of benefits to letting users do some free form pipeline. The DSL I recommend is just that; a recommendation with exception for the vars I wish could be private scope.

          Sam Gleske added a comment - To clarify, I'm not trying to enforce the DSL and am fine with users making use of most of the Jenkins steps. There's a few vars which pose issues if users use them directly due to what they do in the runtime and are only meant for reuse in other vars. Currently Jenkins doesn't have a concept of private vars which is essentially what I want. The other idea was to rely on sandbox to prevent var usage but it doesn't have the infrastructure set up in it. I've considered a YAML only spec but there's a lot of benefits to letting users do some free form pipeline. The DSL I recommend is just that; a recommendation with exception for the vars I wish could be private scope.

          Jesse Glick added a comment -

          If you do not want a variable to be used, then why declare it as a variable at all? Make it a utility inside some class.

          // vars/supported1.groovy
          def call() {
            my.lib.Impl.supported1()
          }
          // vars/supported2.groovy
          def call() {
            my.lib.Impl.supported2()
          }
          // src/my/lib/Impl.groovy
          package my.lib
          public class Impl {
            public static void supported1() {
              internal('one')
            }
            public static void supported2() {
              internal('two')
            }
            private static void internal(String generalValuesForbidden) {
              // …
            }
          }
          

          Now if this is a trusted global library and security is your concern rather than merely enforcing best practices by coworkers operating in good faith, beware that Groovy basically ignores Java access control and might let a malicious pipeline directly call Impl.internal.

          Jesse Glick added a comment - If you do not want a variable to be used, then why declare it as a variable at all? Make it a utility inside some class. // vars/supported1.groovy def call() { my.lib.Impl.supported1() } // vars/supported2.groovy def call() { my.lib.Impl.supported2() } // src/my/lib/Impl.groovy package my.lib public class Impl { public static void supported1() { internal( 'one' ) } public static void supported2() { internal( 'two' ) } private static void internal( String generalValuesForbidden) { // … } } Now if this is a trusted global library and security is your concern rather than merely enforcing best practices by coworkers operating in good faith, beware that Groovy basically ignores Java access control and might let a malicious pipeline directly call Impl.internal .

          Sam Gleske added a comment - - edited

          I have issues with Shared pipeline src directory.

          1. It violates standard conventions of Java (typically set by Maven); for example it has no src/main or src/test just src. It should not have adopted existing conventions and violated them.
          2. It is CPS groovy, like vars, meaning all of the strangeness and restrictions of CPS groovy apply without the NonCPS annotation.
          3. Utilities in src are still accessible by users. Functionally, there's zero difference in a user's ability to use the code in src vs var and so at best it is conceptually organized but not functionally or restrictively separate.

          I need code to be reusable across multiple vars. However, if it is reusable across multiple vars then end users are also able to access it. This was discovered through practice and attempting to self-exploit via own Jenkinsfiles. The only truly effective way is to not make the code available in shared libraries at all and instead package a binary Jar as a one-off custom library-only plugin.

          By the way, I have a library-only custom Jenkins plugin already but there's still the gap and need of quickly extensible but private from end-user Jenkinsfile code necessary.

          In Groovy, even if you explicitly declare a private; it is public

          Sam Gleske added a comment - - edited I have issues with Shared pipeline src directory. It violates standard conventions of Java (typically set by Maven); for example it has no src/main or src/test just src. It should not have adopted existing conventions and violated them. It is CPS groovy, like vars, meaning all of the strangeness and restrictions of CPS groovy apply without the NonCPS annotation. Utilities in src are still accessible by users. Functionally, there's zero difference in a user's ability to use the code in src vs var and so at best it is conceptually organized but not functionally or restrictively separate. I need code to be reusable across multiple vars. However, if it is reusable across multiple vars then end users are also able to access it. This was discovered through practice and attempting to self-exploit via own Jenkinsfiles. The only truly effective way is to not make the code available in shared libraries at all and instead package a binary Jar as a one-off custom library-only plugin. By the way, I have a library-only custom Jenkins plugin already but there's still the gap and need of quickly extensible but private from end-user Jenkinsfile code necessary. In Groovy, even if you explicitly declare a private; it is public

          Sam Gleske added a comment - - edited

          Now if this is a trusted global library and security is your concern
          rather than merely enforcing best practices by coworkers operating in
          good faith, beware that Groovy basically ignores Java access control and
          might let a malicious pipeline directly call Impl.internal.

          I forgot to mention, this is a global shared library and security is a concern. It's not about coworkers operating in good faith. Once you have over 1000 Jenkins users (heck even over 100) you need to start operating Jenkins like it is a public service on the internet (even though it is private).

          In my case, there needs to be a concept of global shared library steps that are available only to global shared libraries and not available to user Jenkinsfiles. It's not really sustainable to offer plugins in all scenarios because even with plugins you might want to call them but not allow user Jenkinsfiles to call them.

          I think extending script security would be a better design for this; enabling block lists for pipeline steps. User Jenkinsfile code is subject to sandbox where global shared pipeline libraries are not.

          Sam Gleske added a comment - - edited Now if this is a trusted global library and security is your concern rather than merely enforcing best practices by coworkers operating in good faith, beware that Groovy basically ignores Java access control and might let a malicious pipeline directly call Impl.internal. I forgot to mention, this is a global shared library and security is a concern. It's not about coworkers operating in good faith. Once you have over 1000 Jenkins users (heck even over 100) you need to start operating Jenkins like it is a public service on the internet (even though it is private). In my case, there needs to be a concept of global shared library steps that are available only to global shared libraries and not available to user Jenkinsfiles. It's not really sustainable to offer plugins in all scenarios because even with plugins you might want to call them but not allow user Jenkinsfiles to call them. I think extending script security would be a better design for this; enabling block lists for pipeline steps. User Jenkinsfile code is subject to sandbox where global shared pipeline libraries are not.

          Jesse Glick added a comment -

          This just sounds like it is outside the design space for Pipeline. If you do not want users freely writing Pipeline script, then you need to deny them the ability to write Pipeline script at all, and only offer templates with predefined parameters, or some sort of (non-embedded) DSL.

          Jesse Glick added a comment - This just sounds like it is outside the design space for Pipeline. If you do not want users freely writing Pipeline script, then you need to deny them the ability to write Pipeline script at all, and only offer templates with predefined parameters, or some sort of (non-embedded) DSL.

            sag47 Sam Gleske
            matthewwalker Matthew Walker
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: