Skip to content

Commit 5bdb9ed

Browse files
tillhackercatmergify[bot]
authored
container credentials (nektos#868)
* Chore: add a snapshot target * Update: support credentials for private containers Resolves: nektos#788 * fix: rework container credentials Signed-off-by: hackercat <me@hackerc.at> * fix: check if Credentials are not nil * fix: return on missing credentials key Co-authored-by: hackercat <me@hackerc.at> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent e793d03 commit 5bdb9ed

4 files changed

Lines changed: 88 additions & 11 deletions

File tree

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,10 @@ ifneq ($(shell git status -s),)
104104
endif
105105
git tag -a -m "releasing v$(NEW_VERSION)" v$(NEW_VERSION)
106106
git push origin v$(NEW_VERSION)
107+
108+
.PHONY: snapshot
109+
snapshot:
110+
goreleaser build \
111+
--rm-dist \
112+
--single-target \
113+
--snapshot

pkg/model/workflow.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,16 @@ func commonKeysMatch(a map[string]interface{}, b map[string]interface{}) bool {
295295

296296
// ContainerSpec is the specification of the container to use for the job
297297
type ContainerSpec struct {
298-
Image string `yaml:"image"`
299-
Env map[string]string `yaml:"env"`
300-
Ports []string `yaml:"ports"`
301-
Volumes []string `yaml:"volumes"`
302-
Options string `yaml:"options"`
303-
Entrypoint string
304-
Args string
305-
Name string
306-
Reuse bool
298+
Image string `yaml:"image"`
299+
Env map[string]string `yaml:"env"`
300+
Ports []string `yaml:"ports"`
301+
Volumes []string `yaml:"volumes"`
302+
Options string `yaml:"options"`
303+
Credentials map[string]string `yaml:"credentials"`
304+
Entrypoint string
305+
Args string
306+
Name string
307+
Reuse bool
307308
}
308309

309310
// Step is the structure of one step in a job

pkg/model/workflow_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,36 @@ jobs:
9999
assert.Contains(t, workflow.Jobs["test2"].Container().Env["foo"], "bar")
100100
}
101101

102+
func TestReadWorkflow_ObjectContainer(t *testing.T) {
103+
yaml := `
104+
name: local-action-docker-url
105+
106+
jobs:
107+
test:
108+
container:
109+
image: r.example.org/something:latest
110+
credentials:
111+
username: registry-username
112+
password: registry-password
113+
env:
114+
HOME: /home/user
115+
runs-on: ubuntu-latest
116+
steps:
117+
- uses: ./actions/docker-url
118+
`
119+
120+
workflow, err := ReadWorkflow(strings.NewReader(yaml))
121+
assert.NoError(t, err, "read workflow should succeed")
122+
assert.Len(t, workflow.Jobs, 1)
123+
124+
container := workflow.GetJob("test").Container()
125+
126+
assert.Contains(t, container.Image, "r.example.org/something:latest")
127+
assert.Contains(t, container.Env["HOME"], "/home/user")
128+
assert.Contains(t, container.Credentials["username"], "registry-username")
129+
assert.Contains(t, container.Credentials["password"], "registry-password")
130+
}
131+
102132
func TestReadWorkflow_StepsTypes(t *testing.T) {
103133
yaml := `
104134
name: invalid step definition

pkg/runner/run_context.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ func (rc *RunContext) startJobContainer() common.Executor {
153153
return true
154154
})
155155

156+
username, password, err := rc.handleCredentials()
157+
if err != nil {
158+
return fmt.Errorf("failed to handle credentials: %s", err)
159+
}
160+
156161
common.Logger(ctx).Infof("\U0001f680 Start image=%s", image)
157162
name := rc.jobContainerName()
158163

@@ -169,8 +174,8 @@ func (rc *RunContext) startJobContainer() common.Executor {
169174
Entrypoint: []string{"/usr/bin/tail", "-f", "/dev/null"},
170175
WorkingDir: rc.Config.ContainerWorkdir(),
171176
Image: image,
172-
Username: rc.Config.Secrets["DOCKER_USERNAME"],
173-
Password: rc.Config.Secrets["DOCKER_PASSWORD"],
177+
Username: username,
178+
Password: password,
174179
Name: name,
175180
Env: envList,
176181
Mounts: mounts,
@@ -836,3 +841,37 @@ func (rc *RunContext) localCheckoutPath() (string, bool) {
836841
}
837842
return "", false
838843
}
844+
845+
func (rc *RunContext) handleCredentials() (username, password string, err error) {
846+
// TODO: remove below 2 lines when we can release act with breaking changes
847+
username = rc.Config.Secrets["DOCKER_USERNAME"]
848+
password = rc.Config.Secrets["DOCKER_PASSWORD"]
849+
850+
container := rc.Run.Job().Container()
851+
if container == nil || container.Credentials == nil {
852+
return
853+
}
854+
855+
if container.Credentials != nil && len(container.Credentials) != 2 {
856+
err = fmt.Errorf("invalid property count for key 'credentials:'")
857+
return
858+
}
859+
860+
ee := rc.NewExpressionEvaluator()
861+
var ok bool
862+
if username, ok = ee.InterpolateWithStringCheck(container.Credentials["username"]); !ok {
863+
err = fmt.Errorf("failed to interpolate container.credentials.username")
864+
return
865+
}
866+
if password, ok = ee.InterpolateWithStringCheck(container.Credentials["password"]); !ok {
867+
err = fmt.Errorf("failed to interpolate container.credentials.password")
868+
return
869+
}
870+
871+
if container.Credentials["username"] == "" || container.Credentials["password"] == "" {
872+
err = fmt.Errorf("container.credentials cannot be empty")
873+
return
874+
}
875+
876+
return username, password, err
877+
}

0 commit comments

Comments
 (0)