Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add mode to require Workflows to use workflowTemplateRef #3149

Merged
merged 19 commits into from
Jun 20, 2020

Conversation

simster7
Copy link
Member

@simster7 simster7 commented Jun 2, 2020

Closes #2867

Currently called "reference mode" and enabled as a flag to the workflow-controller binary.

Procfile Outdated Show resolved Hide resolved
@@ -44,6 +44,7 @@ func NewRootCommand() *cobra.Command {
qps float32
namespaced bool // --namespaced
managedNamespace string // --managed-namespace
referenceMode bool
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name is not final yet.. still thinking of better options

Comment on lines 2714 to 2722
} else if woc.controller.referenceMode {
// If the controller is in reference mode, ensure that the stored spec is identical to the reference spec at every operation
wftSpec, err := woc.fetchWorkflowSpec()
if err != nil {
return nil, wfv1.Arguments{}, err
}
if woc.wf.Status.StoredWorkflowSpec.String() != wftSpec.String() {
return nil, wfv1.Arguments{}, fmt.Errorf("workflowTemplateRef reference may not change during execution when the controller is in reference mode")
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notably, we need to check that the WorkflowTemplate and our own StoredWorkflowSpec have not changed. We do this to prevent attackers from specifying arbitrary code in wf.Status.StoredWorkflowSpec and simply running it by using workflowTemplateRef.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the can change the status, surely they could have changed the spec?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but the key is that you can only change the workflowTemplateRef to another (already existing) WorkflowTemplate. The idea with this feature is to not allow an arbitrary WorkflowSpec from being executed, but instead restricting them to an already present WorkflowTemplate

@simster7 simster7 marked this pull request as ready for review June 8, 2020 20:15
@sonarcloud
Copy link

sonarcloud bot commented Jun 8, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 0 Code Smells

68.8% 68.8% Coverage
0.0% 0.0% Duplication

@alexec
Copy link
Contributor

alexec commented Jun 9, 2020

Could we better enforce this when you submit a workflow?

@simster7
Copy link
Member Author

Could we better enforce this when you submit a workflow?

I think this would make the feature easy to circumvent if the user has edit access to Workflows. Although we could take the official position that for this to work we expect users to not have edit access to existing Workflows.

@alexec
Copy link
Contributor

alexec commented Jun 10, 2020

I think as a user I would want to know that my workflow is invalid - because I've used inline templates - I'd like to know that sooner rather than later - rejected at submission.

I'm assuming we lint the workflow before we execute it (as a result of kubectl create -f my-wf.yaml. Can we have both for free?

@simster7
Copy link
Member Author

Since the restriction is enabled in the controller, we won't know if the controller will reject a Workflow before it is submitted. We could add an endpoint for the controller to tell us if it's in reference mode. The CLI/API would then query the endpoint when doing client-side validation and act appropriately.

However, I think this might be unnecessary since this logic is implemented at the beginning of the operation logic, meaning that a Workflow will fail immediately with a message displayed with the cause:

$ argo submit --watch examples/hello-world.yaml
Name:                hello-world-spth8
Namespace:           argo
ServiceAccount:      default
Status:              Error
Message:             workflows must use workflowTemplateRef to be executed when the controller is in reference mode
Conditions:
 Completed           True
Created:             Mon Jun 08 12:19:43 -0700 (now)
Started:             Mon Jun 08 12:19:43 -0700 (now)
Finished:            Mon Jun 08 12:19:43 -0700 (now)
Duration:            0 seconds

@simster7 simster7 changed the title feat: Add mode to restrict Workflows to workflowTemplateRef feat: Add mode to require Workflows to use workflowTemplateRef Jun 18, 2020
Copy link
Member

@sarabala1979 sarabala1979 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, only one suggestion

}

func (woc *wfOperationCtx) loadExecutionSpec() (wfv1.TemplateReferenceHolder, wfv1.Arguments, error) {

executionParameters := woc.wf.Spec.Arguments

if woc.wf.Spec.WorkflowTemplateRef == nil {
tmplRef := &wfv1.WorkflowStep{Template: woc.wfSpec.Entrypoint}
if woc.controller.Config.WorkflowRequirements.MustUseReference() {
return nil, wfv1.Arguments{}, fmt.Errorf("workflows must use workflowTemplateRef to be executed when the controller is in reference mode")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can return the executionParameters arguments instead of returning new empty structs

return nil, wfv1.Arguments{}, err
}
if woc.wf.Status.StoredWorkflowSpec.String() != wftSpec.String() {
return nil, wfv1.Arguments{}, fmt.Errorf("workflowTemplateRef reference may not change during execution when the controller is in reference mode")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here too for arguments

config/config.go Outdated

type WorkflowRequirements struct {
ReferenceOnly bool `json:"referenceOnly"`
StrictReferenceOnly bool `json:"strictReferenceOnly"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about {reference: {strict:true}}?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jessesuen and I settled on:

data:
  workflowRestrictions:
    templateReferencing: Strict

@simster7 simster7 merged commit 2dae724 into argoproj:master Jun 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add controller mode where only WFs from WFTemplates can be submitted
3 participants