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: Added ssh namespace #2240

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
41 changes: 41 additions & 0 deletions docs-src/content/functions/crypto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,47 @@ preamble: |
recommended to have your resident security experts inspect gomplate's code
before using gomplate for critical security infrastructure!_
funcs:
- name: crypto.SSH
released: v4.2.0 # I hope so
description: |
Namespace for ssh functions
pipeline: false
examples:
- |
$ gomplate -i '{{ crypto.ssh }}'
<namespace SSH [PublicKey]>

- name: crypto.SSH.PublicKey
released: v4.2.0
description: |
Loads [Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell) public key
pipeline: true
arguments:
- name: name
required: false
description: the name of the key in `~/.ssh` or the absolute path to it. The default value is defined by `IdentityFile` in `~/.ssh/config`. If not specified, `~/.ssh/id_rsa.pub` is used.
examples:
- |
$ cat ~/.ssh/id_rsa.pub
gxAedO6GSFC7X+feNqKydIqKlq82R9cnjJPuPLbVvWPB+r08PeJobl++6d9m8EQorpokS+ntqnr35QnIBDWLHk139KhWkOjDOvUHJd6pjOOLhSVapmKPOz1dST4QCweET59STvLHHjNVQfJtWI9zVl4X9S4SoiLDkUUyge+9UnqyA9bAr2P4NkVWZYgf3QnrqoWpRGHz1F7JgV+VmGOlh/Kmc6Q== [email protected]

$ gomplate -i '{{ crypto.SSH.PublicKey }}'
<namespace PublicKey [Blob Comment Format Marshal]>
- |
$ gomplate -i '{{ crypto.SSH.PublicKey.Marshal }}'
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCnEosV4dTgI6CL4YgM4Tfzs6CKdvLL/tarxipWrgEcdwn0TqFn3PmvxSOQWXbQci1Rl2I+U6X3Z4qQ3fafEOlF/bDbwfnY/eUpr9dHnVe1FCbX0tVzCR7OMHg7vGnF3Mta5E9MXMBKupiukgH51hH6fosr90Cvuhj0vsmO3jQL+i1yQxgbc14RCMQuIUZqAA/1Y9JWtucYe4X2uRyby/m2qtHA08kjPTREVd1cMSTM6rCdxnjXgJn7I416ybWnNIwwYeU8q2aKNPIhndSnIBMdDQnnxRCQHgWZXGjF8K8dVl1r3lJWbg/XMXKDWwLXbhRXZwR7/6HDamsV9fkY5Sld9VfKesNiCjaWLlnbe3d6NbdveBcBO6DgDFcshvvtOyu4quBly8EJFpyfeo5V8XQTIVMcLxehXMZNlk0C0PGKQx4xHdxTwFw9IFPbuGNRqRIRwC0YEH3TR4+xBp/gxAedO6GSFC7X+feNqKydIqKlq82R9cnjJPuPLbVvWPB+r08PeJobl++6d9m8EQorpokS+ntqnr35QnIBDWLHk139KhWkOjDOvUHJd6pjOOLhSVapmKPOz1dST4QCweET59STvLHHjNVQfJtWI9zVl4X9S4SoiLDkUUyge+9UnqyA9bAr2P4NkVWZYgf3QnrqoWpRGHz1F7JgV+VmGOlh/Kmc6Q== [email protected]
- |
$ gomplate -i '{{ crypto.SSH.PublicKey.Blob | base64.Encode }}'
AAAAB3NzaC1yc2EAAAADAQABAAACAQCnEosV4dTgI6CL4YgM4Tfzs6CKdvLL/tarxipWrgEcdwn0TqFn3PmvxSOQWXbQci1Rl2I+U6X3Z4qQ3fafEOlF/bDbwfnY/eUpr9dHnVe1FCbX0tVzCR7OMHg7vGnF3Mta5E9MXMBKupiukgH51hH6fosr90Cvuhj0vsmO3jQL+i1yQxgbc14RCMQuIUZqAA/1Y9JWtucYe4X2uRyby/m2qtHA08kjPTREVd1cMSTM6rCdxnjXgJn7I416ybWnNIwwYeU8q2aKNPIhndSnIBMdDQnnxRCQHgWZXGjF8K8dVl1r3lJWbg/XMXKDWwLXbhRXZwR7/6HDamsV9fkY5Sld9VfKesNiCjaWLlnbe3d6NbdveBcBO6DgDFcshvvtOyu4quBly8EJFpyfeo5V8XQTIVMcLxehXMZNlk0C0PGKQx4xHdxTwFw9IFPbuGNRqRIRwC0YEH3TR4+xBp/gxAedO6GSFC7X+feNqKydIqKlq82R9cnjJPuPLbVvWPB+r08PeJobl++6d9m8EQorpokS+ntqnr35QnIBDWLHk139KhWkOjDOvUHJd6pjOOLhSVapmKPOz1dST4QCweET59STvLHHjNVQfJtWI9zVl4X9S4SoiLDkUUyge+9UnqyA9bAr2P4NkVWZYgf3QnrqoWpRGHz1F7JgV+VmGOlh/Kmc6Q==
- |
$ gomplate -i '{{ crypto.SSH.PublicKey.Comment }}'
[email protected]
- |
$ gomplate -i '{{ crypto.SSH.PublicKey.Format }}'
ssh-rsa
- |
$ gomplate -i '{{ (crypto.SSH.PublicKey "e2e_id_ed25519").Marshal }}'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBCLlDopq1aotlRUMw6oJ7Snr+qa+r5X8qxADTuYJumN e2e_key
- name: crypto.Bcrypt
released: v2.6.0
description: |
Expand Down
69 changes: 69 additions & 0 deletions docs/content/functions/crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,75 @@ however, and so can not guarantee correctness of implementation. It is
recommended to have your resident security experts inspect gomplate's code
before using gomplate for critical security infrastructure!_

## `crypto.SSH`

Namespace for ssh functions

_Added in gomplate [v4.2.0](https://github.com/hairyhenderson/gomplate/releases/tag/v4.2.0)_
### Usage

```
crypto.SSH
```


### Examples

```console
$ gomplate -i '{{ crypto.ssh }}'
<namespace SSH [PublicKey]>
```

## `crypto.SSH.PublicKey`

Loads [Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell) public key

_Added in gomplate [v4.2.0](https://github.com/hairyhenderson/gomplate/releases/tag/v4.2.0)_
### Usage

```
crypto.SSH.PublicKey [name]
```
```
name | crypto.SSH.PublicKey
```

### Arguments

| name | description |
|------|-------------|
| `name` | _(optional)_ the name of the key in `~/.ssh` or the absolute path to it. The default value is defined by `IdentityFile` in `~/.ssh/config`. If not specified, `~/.ssh/id_rsa.pub` is used. |

### Examples

```console
$ cat ~/.ssh/id_rsa.pub
gxAedO6GSFC7X+feNqKydIqKlq82R9cnjJPuPLbVvWPB+r08PeJobl++6d9m8EQorpokS+ntqnr35QnIBDWLHk139KhWkOjDOvUHJd6pjOOLhSVapmKPOz1dST4QCweET59STvLHHjNVQfJtWI9zVl4X9S4SoiLDkUUyge+9UnqyA9bAr2P4NkVWZYgf3QnrqoWpRGHz1F7JgV+VmGOlh/Kmc6Q== [email protected]

$ gomplate -i '{{ crypto.SSH.PublicKey }}'
<namespace PublicKey [Blob Comment Format Marshal]>
```
```console
$ gomplate -i '{{ crypto.SSH.PublicKey.Marshal }}'
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCnEosV4dTgI6CL4YgM4Tfzs6CKdvLL/tarxipWrgEcdwn0TqFn3PmvxSOQWXbQci1Rl2I+U6X3Z4qQ3fafEOlF/bDbwfnY/eUpr9dHnVe1FCbX0tVzCR7OMHg7vGnF3Mta5E9MXMBKupiukgH51hH6fosr90Cvuhj0vsmO3jQL+i1yQxgbc14RCMQuIUZqAA/1Y9JWtucYe4X2uRyby/m2qtHA08kjPTREVd1cMSTM6rCdxnjXgJn7I416ybWnNIwwYeU8q2aKNPIhndSnIBMdDQnnxRCQHgWZXGjF8K8dVl1r3lJWbg/XMXKDWwLXbhRXZwR7/6HDamsV9fkY5Sld9VfKesNiCjaWLlnbe3d6NbdveBcBO6DgDFcshvvtOyu4quBly8EJFpyfeo5V8XQTIVMcLxehXMZNlk0C0PGKQx4xHdxTwFw9IFPbuGNRqRIRwC0YEH3TR4+xBp/gxAedO6GSFC7X+feNqKydIqKlq82R9cnjJPuPLbVvWPB+r08PeJobl++6d9m8EQorpokS+ntqnr35QnIBDWLHk139KhWkOjDOvUHJd6pjOOLhSVapmKPOz1dST4QCweET59STvLHHjNVQfJtWI9zVl4X9S4SoiLDkUUyge+9UnqyA9bAr2P4NkVWZYgf3QnrqoWpRGHz1F7JgV+VmGOlh/Kmc6Q== [email protected]
```
```console
$ gomplate -i '{{ crypto.SSH.PublicKey.Blob | base64.Encode }}'
AAAAB3NzaC1yc2EAAAADAQABAAACAQCnEosV4dTgI6CL4YgM4Tfzs6CKdvLL/tarxipWrgEcdwn0TqFn3PmvxSOQWXbQci1Rl2I+U6X3Z4qQ3fafEOlF/bDbwfnY/eUpr9dHnVe1FCbX0tVzCR7OMHg7vGnF3Mta5E9MXMBKupiukgH51hH6fosr90Cvuhj0vsmO3jQL+i1yQxgbc14RCMQuIUZqAA/1Y9JWtucYe4X2uRyby/m2qtHA08kjPTREVd1cMSTM6rCdxnjXgJn7I416ybWnNIwwYeU8q2aKNPIhndSnIBMdDQnnxRCQHgWZXGjF8K8dVl1r3lJWbg/XMXKDWwLXbhRXZwR7/6HDamsV9fkY5Sld9VfKesNiCjaWLlnbe3d6NbdveBcBO6DgDFcshvvtOyu4quBly8EJFpyfeo5V8XQTIVMcLxehXMZNlk0C0PGKQx4xHdxTwFw9IFPbuGNRqRIRwC0YEH3TR4+xBp/gxAedO6GSFC7X+feNqKydIqKlq82R9cnjJPuPLbVvWPB+r08PeJobl++6d9m8EQorpokS+ntqnr35QnIBDWLHk139KhWkOjDOvUHJd6pjOOLhSVapmKPOz1dST4QCweET59STvLHHjNVQfJtWI9zVl4X9S4SoiLDkUUyge+9UnqyA9bAr2P4NkVWZYgf3QnrqoWpRGHz1F7JgV+VmGOlh/Kmc6Q==
```
```console
$ gomplate -i '{{ crypto.SSH.PublicKey.Comment }}'
[email protected]
```
```console
$ gomplate -i '{{ crypto.SSH.PublicKey.Format }}'
ssh-rsa
```
```console
$ gomplate -i '{{ (crypto.SSH.PublicKey "e2e_id_ed25519").Marshal }}'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBCLlDopq1aotlRUMw6oJ7Snr+qa+r5X8qxADTuYJumN e2e_key
```

## `crypto.Bcrypt`

Uses the [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) password hashing algorithm to generate the hash of a given string. Wraps the [`golang.org/x/crypto/brypt`](https://godoc.org/golang.org/x/crypto/bcrypt) package.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/itchyny/gojq v0.12.16
github.com/johannesboyne/gofakes3 v0.0.0-20240217095638-c55a48f17be6
github.com/joho/godotenv v1.5.1
github.com/kevinburke/ssh_config v1.2.0
github.com/lmittmann/tint v1.0.5
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
Expand Down Expand Up @@ -124,7 +125,6 @@ require (
github.com/itchyny/timefmt-go v0.1.6 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
Expand Down
14 changes: 13 additions & 1 deletion internal/funcs/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,27 @@ import (
func CreateCryptoFuncs(ctx context.Context) map[string]interface{} {
f := map[string]interface{}{}

ns := &CryptoFuncs{ctx}
ns := &CryptoFuncs{
ctx: ctx,
ssh: newSSHFuncs(ctx),
}
ns.self = ns

f["crypto"] = func() interface{} { return ns }
return f
}

// CryptoFuncs -
type CryptoFuncs struct {
namespace

ctx context.Context
ssh *SSHFuncs
}

// SSH -
func (f CryptoFuncs) SSH() *SSHFuncs {
return f.ssh
}

// PBKDF2 - Run the Password-Based Key Derivation Function #2 as defined in
Expand Down
25 changes: 19 additions & 6 deletions internal/funcs/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,43 @@ import (
"context"
"io/fs"
"path/filepath"
"sync"

osfs "github.com/hack-pad/hackpadfs/os"
"github.com/hairyhenderson/gomplate/v4/conv"
"github.com/hairyhenderson/gomplate/v4/internal/datafs"
"github.com/hairyhenderson/gomplate/v4/internal/iohelpers"
)

var (
fsys fs.FS
fsysOnce sync.Once
)

// CreateFileFuncs -
func CreateFileFuncs(ctx context.Context) map[string]interface{} {
fsys, err := datafs.FSysForPath(ctx, "/")
if err != nil {
fsys = datafs.WrapWdFS(osfs.NewFS())
}

ns := &FileFuncs{
ctx: ctx,
fs: fsys,
fs: getFS(ctx),
}

return map[string]interface{}{
"file": func() interface{} { return ns },
}
}

func getFS(ctx context.Context) fs.FS {
fsysOnce.Do(func() {
var err error
fsys, err = datafs.FSysForPath(ctx, "/")
if err != nil {
fsys = datafs.WrapWdFS(osfs.NewFS())
}
})

return fsys
}

// FileFuncs -
type FileFuncs struct {
ctx context.Context
Expand Down
12 changes: 12 additions & 0 deletions internal/funcs/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package funcs

import (
"context"
"log/slog"
)

const TraceFuncsLevel = slog.LevelDebug - 1

func trace(ctx context.Context, msg string, attrs ...slog.Attr) {
slog.LogAttrs(ctx, TraceFuncsLevel, msg, attrs...)
}
65 changes: 65 additions & 0 deletions internal/funcs/namespace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package funcs

import (
"fmt"
"reflect"
"strings"
)

var _ fmt.Stringer = (*namespace)(nil)

type namespace struct {
self any //must be pointer to outer struct
}

func (n *namespace) String() string {
ns := n.self
if ns == nil {
return "<namespace>"
}

nsType := reflect.TypeOf(ns)
if nsType.Kind() != reflect.Pointer || nsType.Elem().Kind() != reflect.Struct {
panic("invalid namespace type " + nsType.String() + ": must be pointer to struct")
}

var public []string
public = appendPublicMethods(nsType, public)
nsType = nsType.Elem()
public = appendPublicFields(nsType, public)

nsName := nsType.String()
nsName = strings.TrimPrefix(nsName, "funcs.")
nsName = strings.TrimSuffix(nsName, "Funcs")

return fmt.Sprintf("<namespace %s %s>", nsName, public)
}

func appendPublicFields(nsType reflect.Type, public []string) []string {
for _, field := range reflect.VisibleFields(nsType) {
if !field.IsExported() {
continue
}

public = append(public, field.Name)
}

return public
}

func appendPublicMethods(nsType reflect.Type, public []string) []string {
for i := range nsType.NumMethod() {
method := nsType.Method(i)
if !method.IsExported() {
continue
}

if method.Name == "String" && nsType.Implements(reflect.TypeFor[fmt.Stringer]()) {
continue
}

public = append(public, method.Name)
}

return public
}
Loading