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

client: enable specifying user/group permissions in the template stanza #13755

Merged
merged 20 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
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
4 changes: 4 additions & 0 deletions api/jobs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,8 @@ func TestJobs_Canonicalize(t *testing.T) {
ChangeSignal: stringToPtr(""),
Splay: timeToPtr(5 * time.Second),
Perms: stringToPtr("0644"),
Uid: intToPtr(0),
Gid: intToPtr(0),
LeftDelim: stringToPtr("{{"),
RightDelim: stringToPtr("}}"),
Envvars: boolToPtr(false),
Expand All @@ -778,6 +780,8 @@ func TestJobs_Canonicalize(t *testing.T) {
ChangeSignal: stringToPtr(""),
Splay: timeToPtr(5 * time.Second),
Perms: stringToPtr("0644"),
Uid: intToPtr(0),
Gid: intToPtr(0),
LeftDelim: stringToPtr("{{"),
RightDelim: stringToPtr("}}"),
Envvars: boolToPtr(true),
Expand Down
8 changes: 8 additions & 0 deletions api/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,8 @@ type Template struct {
ChangeSignal *string `mapstructure:"change_signal" hcl:"change_signal,optional"`
Splay *time.Duration `mapstructure:"splay" hcl:"splay,optional"`
Perms *string `mapstructure:"perms" hcl:"perms,optional"`
Uid *int `mapstructure:"uid" hcl:"uid,optional"`
Gid *int `mapstructure:"gid" hcl:"gid,optional"`
LeftDelim *string `mapstructure:"left_delimiter" hcl:"left_delimiter,optional"`
RightDelim *string `mapstructure:"right_delimiter" hcl:"right_delimiter,optional"`
Envvars *bool `mapstructure:"env" hcl:"env,optional"`
Expand Down Expand Up @@ -835,6 +837,12 @@ func (tmpl *Template) Canonicalize() {
if tmpl.Perms == nil {
tmpl.Perms = stringToPtr("0644")
}
if tmpl.Uid == nil {
tmpl.Uid = intToPtr(0)
}
if tmpl.Gid == nil {
tmpl.Gid = intToPtr(0)
}
if tmpl.LeftDelim == nil {
tmpl.LeftDelim = stringToPtr("{{")
}
Expand Down
6 changes: 6 additions & 0 deletions client/allocrunner/taskrunner/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,12 @@ func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[*ctconf.Templa
m := os.FileMode(v)
ct.Perms = &m
}
// Set ownership
if tmpl.Uid != 0 && tmpl.Gid != 0 {
pkazmierczak marked this conversation as resolved.
Show resolved Hide resolved
ct.Uid = &tmpl.Uid
ct.Gid = &tmpl.Gid
}

ct.Finalize()

ctmpls[ct] = tmpl
Expand Down
14 changes: 14 additions & 0 deletions client/allocrunner/taskrunner/template/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"strconv"
"strings"
"sync"
"syscall"
"testing"
"time"

Expand Down Expand Up @@ -512,6 +513,8 @@ func TestTaskTemplateManager_Permissions(t *testing.T) {
DestPath: file,
ChangeMode: structs.TemplateChangeModeNoop,
Perms: "777",
Uid: 503,
Gid: 20,
}

harness := newTestHarness(t, []*structs.Template{template}, false, false)
Expand All @@ -535,6 +538,17 @@ func TestTaskTemplateManager_Permissions(t *testing.T) {
if m := fi.Mode(); m != os.ModePerm {
t.Fatalf("Got mode %v; want %v", m, os.ModePerm)
}

sys := fi.Sys()
uid := int(sys.(*syscall.Stat_t).Uid)
gid := int(sys.(*syscall.Stat_t).Gid)

if uid != template.Uid {
t.Fatalf("Got uid #{uid}; want #{template.Uid}")
}
if gid != template.Gid {
t.Fatalf("Got gid #{uid}; want #{template.Gid}")
}
pkazmierczak marked this conversation as resolved.
Show resolved Hide resolved
}

func TestTaskTemplateManager_Unblock_Static_NomadEnv(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions jobspec/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ func stringToPtr(str string) *string {
return &str
}

// intToPtr returns the pointer to an int
func intToPtr(i int) *int {
return &i
}

// timeToPtr returns the pointer to a time.Duration.
func timeToPtr(t time.Duration) *time.Duration {
return &t
Expand Down
24 changes: 0 additions & 24 deletions jobspec/helper_test.go

This file was deleted.

4 changes: 4 additions & 0 deletions jobspec/parse_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ func parseTemplates(result *[]*api.Template, list *ast.ObjectList) error {
"destination",
"left_delimiter",
"perms",
"uid",
"gid",
"right_delimiter",
"source",
"splay",
Expand All @@ -460,6 +462,8 @@ func parseTemplates(result *[]*api.Template, list *ast.ObjectList) error {
ChangeMode: stringToPtr("restart"),
Splay: timeToPtr(5 * time.Second),
Perms: stringToPtr("0644"),
Uid: intToPtr(0),
Gid: intToPtr(0),
}

dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Expand Down
15 changes: 15 additions & 0 deletions jobspec/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ const (
templateChangeModeRestart = "restart"
)

// Helper functions below are only used by this test suite
func int8ToPtr(i int8) *int8 {
return &i
}
func uint64ToPtr(u uint64) *uint64 {
return &u
}
func int64ToPtr(i int64) *int64 {
return &i
}

func TestParse(t *testing.T) {
ci.Parallel(t)

Expand Down Expand Up @@ -363,6 +374,8 @@ func TestParse(t *testing.T) {
ChangeSignal: stringToPtr("foo"),
Splay: timeToPtr(10 * time.Second),
Perms: stringToPtr("0644"),
Uid: intToPtr(0),
Gid: intToPtr(0),
Envvars: boolToPtr(true),
VaultGrace: timeToPtr(33 * time.Second),
},
Expand All @@ -372,6 +385,8 @@ func TestParse(t *testing.T) {
ChangeMode: stringToPtr(templateChangeModeRestart),
Splay: timeToPtr(5 * time.Second),
Perms: stringToPtr("777"),
Uid: intToPtr(1001),
Gid: intToPtr(20),
LeftDelim: stringToPtr("--"),
RightDelim: stringToPtr("__"),
},
Expand Down
2 changes: 2 additions & 0 deletions jobspec/test-fixtures/basic.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ job "binstore-storagelocker" {
source = "bar"
destination = "bar"
perms = "777"
uid = 1001
gid = 20
left_delimiter = "--"
right_delimiter = "__"
}
Expand Down
5 changes: 0 additions & 5 deletions jobspec2/helper_test.go

This file was deleted.

10 changes: 10 additions & 0 deletions jobspec2/parse_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ func normalizeTemplates(templates []*api.Template) {
if t.Perms == nil {
t.Perms = stringToPtr("0644")
}
if t.Uid == nil {
t.Uid = intToPtr(0)
}
if t.Gid == nil {
t.Gid = intToPtr(0)
}
if t.Splay == nil {
t.Splay = durationToPtr(5 * time.Second)
}
Expand All @@ -121,6 +127,10 @@ func boolToPtr(v bool) *bool {
return &v
}

func intToPtr(v int) *int {
return &v
}

func stringToPtr(v string) *string {
return &v
}
Expand Down
32 changes: 32 additions & 0 deletions nomad/structs/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7044,6 +7044,8 @@ func TestTaskDiff(t *testing.T) {
ChangeSignal: "SIGHUP",
Splay: 1,
Perms: "0644",
Uid: 1001,
Gid: 21,
Wait: &WaitConfig{
Min: helper.TimeToPtr(5 * time.Second),
Max: helper.TimeToPtr(5 * time.Second),
Expand All @@ -7057,6 +7059,8 @@ func TestTaskDiff(t *testing.T) {
ChangeSignal: "SIGHUP2",
Splay: 2,
Perms: "0666",
Uid: 1000,
Gid: 20,
Envvars: true,
},
},
Expand All @@ -7071,6 +7075,8 @@ func TestTaskDiff(t *testing.T) {
ChangeSignal: "SIGHUP",
Splay: 1,
Perms: "0644",
Uid: 1001,
Gid: 21,
Wait: &WaitConfig{
Min: helper.TimeToPtr(5 * time.Second),
Max: helper.TimeToPtr(10 * time.Second),
Expand All @@ -7084,6 +7090,8 @@ func TestTaskDiff(t *testing.T) {
ChangeSignal: "SIGHUP3",
Splay: 3,
Perms: "0776",
Uid: 1002,
Gid: 22,
Wait: &WaitConfig{
Min: helper.TimeToPtr(5 * time.Second),
Max: helper.TimeToPtr(10 * time.Second),
Expand Down Expand Up @@ -7154,6 +7162,12 @@ func TestTaskDiff(t *testing.T) {
Old: "",
New: "false",
},
{
Type: DiffTypeAdded,
Name: "Gid",
Old: "",
New: "22",
},
{
Type: DiffTypeAdded,
Name: "Perms",
Expand All @@ -7172,6 +7186,12 @@ func TestTaskDiff(t *testing.T) {
Old: "",
New: "3",
},
{
Type: DiffTypeAdded,
Name: "Uid",
Old: "",
New: "1002",
},
{
Type: DiffTypeAdded,
Name: "VaultGrace",
Expand Down Expand Up @@ -7234,6 +7254,12 @@ func TestTaskDiff(t *testing.T) {
Old: "true",
New: "",
},
{
Type: DiffTypeDeleted,
Name: "Gid",
Old: "20",
New: "",
},
{
Type: DiffTypeDeleted,
Name: "Perms",
Expand All @@ -7252,6 +7278,12 @@ func TestTaskDiff(t *testing.T) {
Old: "2",
New: "",
},
{
Type: DiffTypeDeleted,
Name: "Uid",
Old: "1000",
New: "",
},
{
Type: DiffTypeDeleted,
Name: "VaultGrace",
Expand Down
3 changes: 3 additions & 0 deletions nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7644,6 +7644,9 @@ type Template struct {

// Perms is the permission the file should be written out with.
Perms string
// User and group that should own the file.
Uid int
Gid int

// LeftDelim and RightDelim are optional configurations to control what
// delimiter is utilized when parsing the template.
Expand Down
4 changes: 4 additions & 0 deletions website/content/api-docs/json-jobs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,10 @@ README][ct].
- `Perms` - Specifies the rendered template's permissions. File permissions are
given as octal of the Unix file permissions `rwxrwxrwx`.

- `Uid` - Specifies the rendered template owner's user ID.

- `Gid` - Specifies the rendered template owner's group ID.

- `RightDelim` - Specifies the right delimiter to use in the template. The default
is "}}" for some templates, it may be easier to use a different delimiter that
does not conflict with the output file itself.
Expand Down
6 changes: 5 additions & 1 deletion website/content/docs/job-specification/template.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ refer to the [Learn Go Template Syntax][gt_learn] Learn guide.
- `perms` `(string: "644")` - Specifies the rendered template's permissions.
File permissions are given as octal of the Unix file permissions `rwxrwxrwx`.

- `uid` `(int: 0)` - Specifies the rendered template owner's user ID.

- `gid` `(int: 0)` - Specifies the rendered template owner's group ID.

- `right_delimiter` `(string: "}}")` - Specifies the right delimiter to use in the
template. The default is "}}" for some templates, it may be easier to use a
different delimiter that does not conflict with the output file itself.
Expand Down Expand Up @@ -561,4 +565,4 @@ options](/docs/configuration/client#options):
[task working directory]: /docs/runtime/environment#task-directories 'Task Directories'
[filesystem internals]: /docs/concepts/filesystem#templates-artifacts-and-dispatch-payloads
[`client.template.wait_bounds`]: /docs/configuration/client#wait_bounds
[rhash]: https://en.wikipedia.org/wiki/Rendezvous_hashing
[rhash]: https://en.wikipedia.org/wiki/Rendezvous_hashing