diff --git a/ABTaskFile b/ABTaskFile index 3e5b72b..bcc5094 100644 --- a/ABTaskFile +++ b/ABTaskFile @@ -136,3 +136,38 @@ commands: description: The port to listen on default: "8081" command: hugo serve -p {{ .Flags.port }} -s docs + + - name: build + type: parent + description: Code build steps + aliases: ["b"] + commands: + - name: binary + description: Build a basic test binary + type: exec + dir: "{{ TaskDir }}" + banner: | + >>> + >>> Building 'ajc' {{ if .Flags.target }}for target '{{ .Flags.target }}'{{ end }} + >>> + flags: + - name: target + description: Target platform to build for + enum: ["linux/amd64"] + short: T + script: | + {{ if eq .Flags.target "linux/amd64" }} + export GOOS=linux + export GOARCH=amd64 + {{ end }} + + cd ajc + go build -o ajc + ls -l ajc + + - name: snapshot + description: Goreleaser snapshot + type: exec + dir: "{{ TaskDir }}" + script: | + goreleaser release --snapshot --clean diff --git a/client_options.go b/client_options.go index a7cd061..a8ab621 100644 --- a/client_options.go +++ b/client_options.go @@ -6,6 +6,7 @@ package asyncjobs import ( "crypto/ed25519" + "encoding/hex" "fmt" "time" @@ -272,6 +273,23 @@ func TaskSigningSeedFile(sf string) ClientOpt { } } +// TaskVerificationKeyHexEncoded sets a public key used to verify tasks, hex encoded string +func TaskVerificationKeyHexEncoded(pks string) ClientOpt { + return func(opts *ClientOpts) error { + if pks == "" { + return nil + } + + pk, err := hex.DecodeString(pks) + if err != nil { + return err + } + + opts.publicKey = pk + return nil + } +} + // TaskVerificationKey sets a public key used to verify tasks func TaskVerificationKey(pk ed25519.PublicKey) ClientOpt { return func(opts *ClientOpts) error { diff --git a/docs/content/reference/security.md b/docs/content/reference/security.md index 43f264d..fab1372 100644 --- a/docs/content/reference/security.md +++ b/docs/content/reference/security.md @@ -21,19 +21,22 @@ Then we can configure the client: ```go client, err := asyncjobs.NewClient( - asyncjobs.NatsContext("AJC"), + asyncjobs.NatsContext("AJC"), - // when tasks are created sign using this ed25519.PrivateKey, see also TaskSigningSeedFile() + // when tasks are created sign using this ed25519.PrivateKey, see also TaskSigningSeedFile() asyncjobs.TaskSigningKey(prik), - - // when loading tasks verify using this ed25519.PublicKey, see also TaskVerificationKeyFile() - asyncjobs.TaskVerificationKey(pubk), - - // support loading unsigned tasks when a verification method is set, disabled by default - asyncjobs.TaskSignaturesOptional(), - ) + + // when loading tasks verify using this ed25519.PublicKey, see also TaskVerificationKeyFile() + asyncjobs.TaskVerificationKey(pubk), + + // support loading unsigned tasks when a verification method is set, disabled by default + asyncjobs.TaskSignaturesOptional(), +) panicIfErr(err) ``` On the command line the `ajc tasks` command has `--sign` and `--verify` flags which can either be hex encoded keys -or paths to files holding them in hex encoded format. \ No newline at end of file +or paths to files holding them in hex encoded format. + +Docker containers built using `ajc package docker` can set a key in the environment variable `AJ_VERIFICATION_KEY` and +can opt into optional signatures at build time by setting `task_signatures_optional: true` in the `asyncjobs.yaml`. \ No newline at end of file diff --git a/generators/fs/godocker/main.go.templ b/generators/fs/godocker/main.go.templ index 9c1df5b..f430932 100644 --- a/generators/fs/godocker/main.go.templ +++ b/generators/fs/godocker/main.go.templ @@ -40,6 +40,7 @@ The following Environment variables are supported: - AJ_NATS_CONTEXT: The name of a NATS Context to use for connections - AJ_CONCURRENCY: The number of concurrent handlers that can be run - AJ_RETRY_POLICY: The retry policy to use [{{ RetryNamesList }}] + - AJ_VERIFICATION_KEY: A hex encoded ed25519 public key that will verify job signatures Prometheus statistics are Exposed on port http://0.0.0.0:8080/metrics @@ -103,6 +104,9 @@ func main() { retryPolicy = "{{ .Package.RetryPolicy }}" } + verificationKey := os.Getenv("AJ_VERIFICATION_KEY") + sigsOptional := "{{ .Package.TaskSignaturesOptional }}" == "" + log := logrus.NewEntry(logger) log.Printf("Choria Async Jobs Handler Service {{.Package.Name}} build settings") @@ -110,6 +114,10 @@ func main() { log.Printf("Work Queue: %s", wq) log.Printf("Concurrency: %d", concurrency) log.Printf("Retry Policy: %s", retryPolicy) + if verificationKey != "" { + log.Printf("Verification Key: %s", verificationKey) + log.Printf("Verification Optional: %t", sigsOptional) + } {{- range $state := .Package.DiscardStates }} log.Printf("Discard State: {{$state}}") {{- end }} @@ -122,6 +130,10 @@ func main() { aj.ClientConcurrency(concurrency), aj.CustomLogger(log), aj.RetryBackoffPolicyName(retryPolicy), + aj.TaskVerificationKeyHexEncoded(verificationKey), +{{- if .Package.TaskSignaturesOptional }} + aj.TaskSignaturesOptional(), +{{- end }} {{- range $state := .Package.DiscardStates }} aj.DiscardTaskStatesByName("{{$state}}"), {{- end }} diff --git a/generators/package.go b/generators/package.go index ffc6daa..27b5775 100644 --- a/generators/package.go +++ b/generators/package.go @@ -26,6 +26,8 @@ type Package struct { RetryPolicy string `yaml:"retry"` // DiscardStates indicates what termination states to discard DiscardStates []string `yaml:"discard"` + // TaskSignaturesOptional allows unsigned tasks to be used when AJ_VERIFICATION_KEY is set + TaskSignaturesOptional bool `yaml:"task_signatures_optional"` } // TaskHandler is an individual Task Handler