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(api): disable project secrets auto injection for given regions #6048

Merged
merged 4 commits into from
Jan 4, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
doc: cr
  • Loading branch information
richardlt committed Dec 29, 2021
commit 535e83dc42bae76db5c35a1c35aabd436b0a5723
1 change: 1 addition & 0 deletions docs/content/docs/concepts/requirement/_index.md
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ Requirement types:
- [Memory]({{< relref "/docs/concepts/requirement/requirement_memory.md" >}})
- [OS & Architecture]({{< relref "/docs/concepts/requirement/requirement_os_arch.md" >}})
- [Region]({{< relref "/docs/concepts/requirement/requirement_region.md" >}})
- [Secret]({{< relref "/docs/concepts/requirement/requirement_secret.md" >}})

A [Job]({{< relref "/docs/concepts/job.md" >}}) will be executed by a **worker**.

42 changes: 42 additions & 0 deletions docs/content/docs/concepts/requirement/requirement_secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: "Secret Requirement"
weight: 4
---

The `Secret` prerequisite allows you to require a worker to start with some project's secrets when those secrets are not automatically injected.

Secret automatic injection can be disabled if a job requires to run in a specific region (using a "Region" prerequisite) that was added in CDS API configuration (key: skipProjectSecretsOnRegion).

The value for the requirement should be a valid regex. In the following example it is used to match both default SSH and PGP keys for a CDS project.

Example of job configuration:
```
- job: build
requirements:
- region: myregion
- secret: ^cds.key.proj-(ssh|pgp)-test.priv$
steps:
...
```

Example of CDS API configuration:
```
[api]
...
[api.secrets]
...
skipProjectSecretsOnRegion = ["myregion"]
```

Example of CDS Hatchery configuration:
```
[hatchery]
[hatchery.local]
...
[hatchery.local.commonConfiguration]
...
[hatchery.local.commonConfiguration.provision]
...
region = "myregion"
ignoreJobWithNoRegion = true
```
30 changes: 25 additions & 5 deletions engine/api/workflow_queue_test.go
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import (
"net/url"
"os"
"path"
"strings"
"testing"
"time"

@@ -595,7 +596,18 @@ func Test_postTakeWorkflowJobHandler(t *testing.T) {

assert.Equal(t, "cdn.net:4545", pbji.GelfServiceAddr)
assert.Equal(t, true, pbji.GelfServiceAddrEnableTLS)
assert.Len(t, pbji.Secrets, 5)
require.Len(t, pbji.Secrets, 5)
var foundDefaultSSHKey, foundDefaultPGPKey bool
for _, s := range pbji.Secrets {
if s.Name == "cds.key.proj-ssh-"+strings.ToLower(pbji.ProjectKey)+".priv" {
foundDefaultSSHKey = true
}
if s.Name == "cds.key.proj-pgp-"+strings.ToLower(pbji.ProjectKey)+".priv" {
foundDefaultPGPKey = true
}
}
require.True(t, foundDefaultSSHKey)
require.True(t, foundDefaultPGPKey)

run, err := workflow.LoadNodeJobRun(context.TODO(), api.mustDB(), api.Cache, ctx.job.ID)
require.NoError(t, err)
@@ -623,21 +635,18 @@ func Test_postTakeWorkflowJobWithFilteredSecretHandler(t *testing.T) {
require.NoError(tt, pipeline.UpdateJob(context.TODO(), tx, &pip.Stages[0].Jobs[0]))
})

// Prepare VCS Mock
mockVCSSservice, _, _ := assets.InitCDNService(t, db)
t.Cleanup(func() {
_ = services.Delete(db, mockVCSSservice) // nolint
})

//Register the worker
testRegisterWorker(t, api, db, router, &ctx)

uri := router.GetRoute("POST", api.postTakeWorkflowJobHandler, map[string]string{
"permJobID": fmt.Sprintf("%d", ctx.job.ID),
})
require.NotEmpty(t, uri)

//This call must work
req := assets.NewJWTAuthentifiedRequest(t, ctx.workerToken, "POST", uri, nil)
rec := httptest.NewRecorder()
router.Mux.ServeHTTP(rec, req)
@@ -646,7 +655,18 @@ func Test_postTakeWorkflowJobWithFilteredSecretHandler(t *testing.T) {
pbji := &sdk.WorkflowNodeJobRunData{}
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), pbji))

assert.Len(t, pbji.Secrets, 4)
require.Len(t, pbji.Secrets, 4)
var foundDefaultSSHKey, foundDefaultPGPKey bool
for _, s := range pbji.Secrets {
if s.Name == "cds.key.proj-ssh-"+strings.ToLower(pbji.ProjectKey)+".priv" {
foundDefaultSSHKey = true
}
if s.Name == "cds.key.proj-pgp-"+strings.ToLower(pbji.ProjectKey)+".priv" {
foundDefaultPGPKey = true
}
}
require.True(t, foundDefaultSSHKey)
require.False(t, foundDefaultPGPKey)
}

func Test_postTakeWorkflowInvalidJobHandler(t *testing.T) {
7 changes: 7 additions & 0 deletions sdk/exportentities/pipeline.go
Original file line number Diff line number Diff line change
@@ -59,6 +59,7 @@ type Requirement struct {
Memory string `json:"memory,omitempty" yaml:"memory,omitempty"`
OSArchRequirement string `json:"os-architecture,omitempty" yaml:"os-architecture,omitempty"`
RegionRequirement string `json:"region,omitempty" yaml:"region,omitempty"`
SecretRequirement string `json:"secret,omitempty" yaml:"secret,omitempty"`
}

// ServiceRequirement represents an exported sdk.Requirement of type ServiceRequirement
@@ -152,6 +153,8 @@ func NewRequirements(req []sdk.Requirement) []Requirement {
res = append(res, Requirement{RegionRequirement: r.Value})
case sdk.MemoryRequirement:
res = append(res, Requirement{Memory: r.Value})
case sdk.SecretRequirement:
res = append(res, Requirement{SecretRequirement: r.Value})
}
}
return res
@@ -229,6 +232,10 @@ func computeJobRequirements(req []Requirement) []sdk.Requirement {
name = r.Service.Name
val = r.Service.Value
tpe = sdk.ServiceRequirement
} else if r.SecretRequirement != "" {
name = "secret"
val = r.SecretRequirement
tpe = sdk.SecretRequirement
}
res[i] = sdk.Requirement{
Name: name,