Add templating coalesce function (#4492)
This commit is contained in:
1 parent
7105270cd5
commit
4542eef22b
8 files changed
+52
-8
No files matched your search
@@ -11,6 +11,12 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
|
||||
the alias value. Crate an alias with
|
||||
`boundary aliases create target -value example.boundary -destination-id ttcp_1234567890`
|
||||
and connect to a target using an alias using `boundary connect example.boundary`
|
||||
* templating: A new templating function `coalesce` can be used to match a
|
||||
template against multiple possible values, returning the first non-empty
|
||||
value. As an example, this can be used in a credential library to allow a
|
||||
username value that might be comprised of a name or login name depending on
|
||||
the auth method, e.g. `{{ coalesce .Account.Name .Account.LoginName}}`
|
||||
([PR](https://github.com/hashicorp/boundary/pull/4492)))
|
||||
|
||||
### Added dependency
|
||||
|
||||
|
||||
@@ -1345,6 +1345,17 @@ func TestRepository_sshCertIssuingCredentialLibrary_retrieveCredential(t *testin
|
||||
opts: []Option{WithKeyType(KeyTypeEcdsa), WithKeyBits(256)},
|
||||
retOpts: []credential.Option{credential.WithTemplateData(template.Data{Account: template.Account{Email: util.Pointer("rise-of-the-template@foobar.com")}})},
|
||||
},
|
||||
{
|
||||
name: "vault issue ec(256) cert with coalesce username",
|
||||
username: `{{coalesce .Account.LoginName .Account.Name .Account.Email}}`,
|
||||
expected: map[string]any{
|
||||
"username": "name-that-name",
|
||||
"valid_principals": []string{"name-that-name"},
|
||||
},
|
||||
vaulthPath: "ssh/issue/boundary",
|
||||
opts: []Option{WithKeyType(KeyTypeEcdsa), WithKeyBits(256)},
|
||||
retOpts: []credential.Option{credential.WithTemplateData(template.Data{Account: template.Account{Name: util.Pointer("name-that-name"), LoginName: util.Pointer(""), Email: util.Pointer("rise-of-the-template@foobar.com")}})},
|
||||
},
|
||||
{
|
||||
name: "vault issue ec(384) cert with disallowed extension",
|
||||
username: "username-10-because-789",
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"hash"
|
||||
"hash/fnv"
|
||||
"log"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
@@ -599,8 +600,10 @@ func (v verifier) performAuthCheck(ctx context.Context) (
|
||||
return
|
||||
}
|
||||
userData.Account.Name = util.Pointer(acct.GetName())
|
||||
log.Println("account name", *userData.Account.Name)
|
||||
userData.Account.Email = util.Pointer(acct.GetEmail())
|
||||
userData.Account.LoginName = util.Pointer(acct.GetLoginName())
|
||||
log.Println("account login name", *userData.Account.LoginName)
|
||||
userData.Account.Subject = util.Pointer(acct.GetSubject())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,3 +12,14 @@ func truncateFrom(str, sep string) string {
|
||||
before, _, _ := strings.Cut(str, sep)
|
||||
return before
|
||||
}
|
||||
|
||||
// coalesce will return the first non-empty string in the list of strings, and
|
||||
// an empty string if all parameters are empty.
|
||||
func coalesce(vals ...string) string {
|
||||
for _, val := range vals {
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -33,6 +33,7 @@ func New(ctx context.Context, raw string) (*Parsed, error) {
|
||||
raw: raw,
|
||||
funcMap: map[string]any{
|
||||
"truncateFrom": truncateFrom,
|
||||
"coalesce": coalesce,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestErrors(t *testing.T) {
|
||||
require.NotNil(parsed)
|
||||
assert.Equal(ts, parsed.raw)
|
||||
assert.NotNil(parsed.tmpl)
|
||||
assert.Len(parsed.funcMap, 1)
|
||||
assert.Len(parsed.funcMap, 2)
|
||||
|
||||
// Test out errors on the parsed value
|
||||
|
||||
@@ -102,6 +102,8 @@ func TestGenerate(t *testing.T) {
|
||||
{{ .Account.Subject }}
|
||||
{{ .Account.Email }}
|
||||
{{ truncateFrom .Account.Email "@" }}
|
||||
{{ coalesce "" .Account.LoginName .Account.Name }}
|
||||
{{ coalesce "" "" .Account.Name .Account.LoginName }}
|
||||
`)
|
||||
|
||||
parsed, err := New(ctx, raw)
|
||||
@@ -128,6 +130,8 @@ accountLoginName
|
||||
accountSubject
|
||||
account@email.com
|
||||
account
|
||||
accountLoginName
|
||||
accountName
|
||||
`)
|
||||
|
||||
assert.Equal(exp, out)
|
||||
|
||||
@@ -19,10 +19,11 @@ type Data struct {
|
||||
// request to be from a different auth method, in which case it may not match
|
||||
// what's in the Account struct.
|
||||
type User struct {
|
||||
Id *string
|
||||
Name *string
|
||||
FullName *string
|
||||
Email *string
|
||||
Id *string
|
||||
Name *string
|
||||
LoginName *string
|
||||
FullName *string
|
||||
Email *string
|
||||
}
|
||||
|
||||
// Account contains account information. Not all fields will always be
|
||||
|
||||
@@ -105,14 +105,21 @@ This value may not be populated, or it may be different from the account name us
|
||||
- `{{.Account.Subject}}` - The account's subject, if a subject is used by that type of account.
|
||||
- `{{.Account.Email}}` - The account's email, if email is used by that type of account.
|
||||
|
||||
Additionally, there is currently a single function that strips the rest of a string after a specified substring.
|
||||
This function is useful for pulling a user or account name from an email address.
|
||||
The following example turns `foo@example.com` into `foo`:
|
||||
Additionally, there are a couple of useful functions:
|
||||
|
||||
The `trucateFrom` function strips the rest of a string after a specified
|
||||
substring. This function is useful for pulling a user or account name from an
|
||||
email address. The following example turns `foo@example.com` into `foo`:
|
||||
|
||||
`{{truncateFrom .Account.Email "@"}}`
|
||||
|
||||
The example above uses the account email, but it could be any other parameter.
|
||||
|
||||
The `coalesce` function chooses the first non-empty value out of the list. This
|
||||
is useful when using account names/login names since only one may be populated:
|
||||
|
||||
`{{coalesce .Account.Name .Account.LoginName}}`
|
||||
|
||||
## Tutorial
|
||||
|
||||
Refer to the [SSH certificate injection with HCP Boundary](/boundary/tutorials/access-management/hcp-certificate-injection) tutorial to learn how to configure credential injection with SSH certificates using Vault.
|
||||
|
||||
Reference in new issue
Block a user