Skip to content

Commit

Permalink
template: check namespace and region before submitting templates to t…
Browse files Browse the repository at this point in the history
…he client (hashicorp#366)

If Nomad uses ACLs that restrict our access by namespace or region, we need to extract namespace/region information from the raw templates before submitting them to the client; otherwise we get a 403.
  • Loading branch information
pkazmierczak committed Jun 28, 2023
1 parent 1ae3ee3 commit ff62241
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 89 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ IMPROVEMENTS:
* template: Render templates other than Nomad job specifications inside `templates/` [[GH-303](https://github.com/hashicorp/nomad-pack/pull/303)]
* template: Automatically format templates before outputting [[GH-311](https://github.com/hashicorp/nomad-pack/pull/311)]
* template: Skip templates that would render to just whitespace [[GH-313](https://github.com/hashicorp/nomad-pack/pull/313)]
* template: Extract namespace and region from the templates before submitting them to the client [[GH-366](https://github.com/hashicorp/nomad-pack/pull/366)]
* vars: Add flag to ignore variables provided in the given var-files unused by the pack [[GH-315](https://github.com/hashicorp/nomad-pack/pull/315)]

## 0.0.1-techpreview.3 (July 21, 2022)
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/hashicorp/hcl v1.0.1-vault-5
github.com/hashicorp/hcl/v2 v2.16.2
github.com/hashicorp/nomad v1.4.2
github.com/hashicorp/nomad/api v0.0.0-20230530070532-91a434fdfc15
github.com/hashicorp/nomad/api v0.0.0-20230626161812-d20faf58554d
github.com/kr/text v0.2.0
github.com/lab47/vterm v0.0.0-20211107042118-80c3d2849f9c
github.com/mattn/go-isatty v0.0.19
Expand All @@ -35,7 +35,6 @@ require (
github.com/zclconf/go-cty v1.13.2
golang.org/x/term v0.8.0
golang.org/x/text v0.9.0
google.golang.org/grpc v1.55.0
)

require (
Expand Down Expand Up @@ -275,6 +274,7 @@ require (
google.golang.org/api v0.124.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230524185152-1884fd1fac28 // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/fsnotify.v1 v1.4.7 // indirect
gopkg.in/resty.v1 v1.12.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -970,8 +970,8 @@ github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 h1:lc
github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q=
github.com/hashicorp/nomad v1.4.2 h1:ywXODBplzOKu/gqfBVWOwbJcFodjR7tlIHidhv4Gbao=
github.com/hashicorp/nomad v1.4.2/go.mod h1:fs+8dvfSnbARTFKYTnou4igUT4vfCLuB4koPIpeXH98=
github.com/hashicorp/nomad/api v0.0.0-20230530070532-91a434fdfc15 h1:HoN88l/jx+RoD7USW3/NDC9XE1Q0jI8/GnxPVSiHems=
github.com/hashicorp/nomad/api v0.0.0-20230530070532-91a434fdfc15/go.mod h1:Xjd3OXUTfsWbCCBsQd3EdfPTz5evDi+fxqdvpN+WqQg=
github.com/hashicorp/nomad/api v0.0.0-20230626161812-d20faf58554d h1:o0JcARPfcPTdECQDDfzih+nLxkoDtlJCSqrr3pQEupA=
github.com/hashicorp/nomad/api v0.0.0-20230626161812-d20faf58554d/go.mod h1:Xjd3OXUTfsWbCCBsQd3EdfPTz5evDi+fxqdvpN+WqQg=
github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM=
github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
github.com/hashicorp/raft v1.3.11 h1:p3v6gf6l3S797NnK5av3HcczOC1T5CLoaRvg0g9ys4A=
Expand Down
61 changes: 0 additions & 61 deletions internal/cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ import (

"github.com/hashicorp/go-hclog"
"github.com/hashicorp/nomad/api"
"github.com/mitchellh/go-wordwrap"
"github.com/posener/complete"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/hashicorp/nomad-pack/internal/pkg/cache"
flag "github.com/hashicorp/nomad-pack/internal/pkg/flag"
Expand Down Expand Up @@ -229,32 +226,6 @@ func (c *baseCommand) ensureCache() error {
// to configure the set with your own custom options.
func (c *baseCommand) flagSet(bit flagSetBit, f func(*flag.Sets)) *flag.Sets {
set := flag.NewSets()
{
// f := set.NewSet("Global Options")

// f.BoolVar(&flag.BoolVar{
// Name: "plain",
// Target: &c.flagPlain,
// Default: false,
// Usage: "Plain output: no colors, no animation.",
// })

// f.StringVar(&flag.StringVar{
// Name: "app",
// Target: &c.flagApp,
// Default: "",
// Usage: "App to target. Certain commands require a single app target for " +
// "Waypoint configurations with multiple apps. If you have a single app, " +
// "then this can be ignored.",
// })

// f.StringVar(&flag.StringVar{
// Name: "workspace",
// Target: &c.flagWorkspace,
// Default: "default",
// Usage: "Workspace to operate in.",
// })
}
if bit&flagSetOperation != 0 {
f := set.NewSet("Operation Options")
f.StringSliceVarP(&flag.StringSliceVarP{
Expand Down Expand Up @@ -435,38 +406,6 @@ var (
ErrParsingArgsOrFlags = "error parsing args or flags"
)

func Humanize(err error) string {
if err == nil {
return ""
}

if IsCanceled(err) {
return "operation canceled"
}

v := err.Error()
if s, ok := status.FromError(err); ok {
v = s.Message()
}

return wordwrap.WrapString(v, 80)
}

// IsCanceled is true if the error represents a cancellation. This detects
// context cancellation as well as gRPC cancellation codes.
func IsCanceled(err error) bool {
if err == context.Canceled {
return true
}

s, ok := status.FromError(err)
if !ok {
return false
}

return s.Code() == codes.Canceled
}

func (c *baseCommand) getAPIClient() (*api.Client, error) {
return api.NewClient(clientOptsFromCLI(c))
}
24 changes: 22 additions & 2 deletions internal/runner/job/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package job
import (
"fmt"
"os"
"regexp"
"time"

"github.com/hashicorp/nomad/api"
Expand Down Expand Up @@ -229,14 +230,30 @@ func (r *Runner) ParseTemplates() []*errors.WrappedUIContext {
var outputErrors []*errors.WrappedUIContext

for tplName, tpl := range r.rawTemplates {
// if a template contains region or namespace information, it needs to be passed
// to the client before calling the parse methods, otherwise they might fail in
// case ACL restricts our permissions
namespaceRe := regexp.MustCompile(`(?m)namespace = \"(\w+)`)
regionRe := regexp.MustCompile(`(?m)region = \"(\w+)`)

if nsRes := namespaceRe.FindStringSubmatch(tpl); len(nsRes) > 1 {
r.client.SetNamespace(nsRes[1])
}

if regRes := regionRe.FindStringSubmatch(tpl); len(regRes) > 1 {
r.client.SetRegion(regRes[1])
}

ncJob, err := r.client.Jobs().ParseHCLOpts(&api.JobsParseRequest{
JobHCL: tpl,
HCLv1: r.cfg.RunConfig.HCL1,
Canonicalize: false,
})
if err != nil {
outputErrors = append(outputErrors, newValidationDeployerError(err, validationSubjParseFailed, tplName))
outputErrors = append(
outputErrors,
newValidationDeployerError(err, validationSubjParseFailed, tplName),
)
continue
}

Expand All @@ -246,7 +263,10 @@ func (r *Runner) ParseTemplates() []*errors.WrappedUIContext {
Canonicalize: true,
})
if err != nil {
outputErrors = append(outputErrors, newValidationDeployerError(err, validationSubjParseFailed, tplName))
outputErrors = append(
outputErrors,
newValidationDeployerError(err, validationSubjParseFailed, tplName),
)
continue
}

Expand Down
22 changes: 0 additions & 22 deletions internal/runner/job/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,6 @@ import (
"github.com/hashicorp/nomad/api"
)

func (r *Runner) newQueryOptsFromJob(job ParsedTemplate) *api.QueryOptions {
opts := &api.QueryOptions{}
if job.HasRegion() {
opts.Region = *job.Job().Region
}
if job.HasNamespace() {
opts.Namespace = *job.Job().Namespace
}
return opts
}

func (r *Runner) newQueryOptsFromClientJob(job *api.Job) *api.QueryOptions {
opts := &api.QueryOptions{}
if job.Region != nil {
opts.Region = *job.Region
}
if job.Namespace != nil {
opts.Namespace = *job.Namespace
}
return opts
}

func (r *Runner) newWriteOptsFromJob(job ParsedTemplate) *api.WriteOptions {
opts := &api.WriteOptions{}
if job.HasRegion() {
Expand Down

0 comments on commit ff62241

Please sign in to comment.