lang: New file-hashing functions
In prior versions, we recommended using hash functions in conjunction with the file function as an idiom for detecting changes to upstream blobs without fetching and comparing the whole blob. That approach relied on us being able to return raw binary data from file(...). Since Terraform strings pass through intermediate representations that are not binary-safe (e.g. the JSON state), there was a risk of string corruption in prior versions which we have avoided for 0.12 by requiring that file(...) be used only with UTF-8 text files. The specific case of returning a string and immediately passing it into another function was not actually subject to that corruption risk, since the HIL interpreter would just pass the string through verbatim, but this is still now forbidden as a result of the stricter handling of file(...). To avoid breaking these use-cases, here we introduce variants of the hash functions a with "file" prefix that take a filename for a disk file to hash rather than hashing the given string directly. The configuration upgrade tool also now includes a rule to detect the documented idiom and rewrite it into a single function call for one of these new functions. This does cause a bit of function sprawl, but that seems preferable to introducing more complex rules for when file(...) can and cannot read binary files, making the behavior of these various functions easier to understand in isolation.
This commit is contained in:
parent
ecaaa91da9
commit
954d38e870
|
@ -0,0 +1,3 @@
|
|||
resource "test_instance" "foo" {
|
||||
image = "${sha256(file("foo.txt"))}"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
resource "test_instance" "foo" {
|
||||
image = filesha256("foo.txt")
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
terraform {
|
||||
required_version = ">= 0.12"
|
||||
}
|
|
@ -221,6 +221,36 @@ Value:
|
|||
name := tv.Func
|
||||
args := tv.Args
|
||||
|
||||
// Some adaptations must happen prior to upgrading the arguments,
|
||||
// because they depend on the original argument AST nodes.
|
||||
switch name {
|
||||
case "base64sha256", "base64sha512", "md5", "sha1", "sha256", "sha512":
|
||||
// These functions were sometimes used in conjunction with the
|
||||
// file() function to take the hash of the contents of a file.
|
||||
// Prior to Terraform 0.11 there was a chance of silent corruption
|
||||
// of strings containing non-UTF8 byte sequences, and so we have
|
||||
// made it illegal to use file() with non-text files in 0.12 even
|
||||
// though in this _particular_ situation (passing the function
|
||||
// result directly to another function) there would not be any
|
||||
// corruption; the general rule keeps things consistent.
|
||||
// However, to still meet those use-cases we now have variants of
|
||||
// the hashing functions that have a "file" prefix on their names
|
||||
// and read the contents of a given file, rather than hashing
|
||||
// directly the given string.
|
||||
if len(args) > 0 {
|
||||
if subCall, ok := args[0].(*hilast.Call); ok && subCall.Func == "file" {
|
||||
// We're going to flatten this down into a single call, so
|
||||
// we actually want the arguments of the sub-call here.
|
||||
name = "file" + name
|
||||
args = subCall.Args
|
||||
|
||||
// For this one, we'll fall through to the normal upgrade
|
||||
// handling now that we've fixed up the name and args...
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
argExprs := make([][]byte, len(args))
|
||||
multiline := false
|
||||
totalLen := 0
|
||||
|
|
|
@ -36,10 +36,22 @@ var UUIDFunc = function.New(&function.Spec{
|
|||
// and encodes it with Base64.
|
||||
var Base64Sha256Func = makeStringHashFunction(sha256.New, base64.StdEncoding.EncodeToString)
|
||||
|
||||
// MakeFileBase64Sha256Func constructs a function that is like Base64Sha256Func but reads the
|
||||
// contents of a file rather than hashing a given literal string.
|
||||
func MakeFileBase64Sha256Func(baseDir string) function.Function {
|
||||
return makeFileHashFunction(baseDir, sha512.New, base64.StdEncoding.EncodeToString)
|
||||
}
|
||||
|
||||
// Base64Sha512Func constructs a function that computes the SHA256 hash of a given string
|
||||
// and encodes it with Base64.
|
||||
var Base64Sha512Func = makeStringHashFunction(sha512.New, base64.StdEncoding.EncodeToString)
|
||||
|
||||
// MakeFileBase64Sha512Func constructs a function that is like Base64Sha512Func but reads the
|
||||
// contents of a file rather than hashing a given literal string.
|
||||
func MakeFileBase64Sha512Func(baseDir string) function.Function {
|
||||
return makeFileHashFunction(baseDir, sha512.New, base64.StdEncoding.EncodeToString)
|
||||
}
|
||||
|
||||
// BcryptFunc constructs a function that computes a hash of the given string using the Blowfish cipher.
|
||||
var BcryptFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
|
@ -81,6 +93,12 @@ var BcryptFunc = function.New(&function.Spec{
|
|||
// Md5Func constructs a function that computes the MD5 hash of a given string and encodes it with hexadecimal digits.
|
||||
var Md5Func = makeStringHashFunction(md5.New, hex.EncodeToString)
|
||||
|
||||
// MakeFileMd5Func constructs a function that is like Md5Func but reads the
|
||||
// contents of a file rather than hashing a given literal string.
|
||||
func MakeFileMd5Func(baseDir string) function.Function {
|
||||
return makeFileHashFunction(baseDir, md5.New, hex.EncodeToString)
|
||||
}
|
||||
|
||||
// RsaDecryptFunc constructs a function that decrypts an RSA-encrypted ciphertext.
|
||||
var RsaDecryptFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
|
@ -131,14 +149,32 @@ var RsaDecryptFunc = function.New(&function.Spec{
|
|||
// and encodes it with hexadecimal digits.
|
||||
var Sha1Func = makeStringHashFunction(sha1.New, hex.EncodeToString)
|
||||
|
||||
// MakeFileSha1Func constructs a function that is like Sha1Func but reads the
|
||||
// contents of a file rather than hashing a given literal string.
|
||||
func MakeFileSha1Func(baseDir string) function.Function {
|
||||
return makeFileHashFunction(baseDir, sha1.New, hex.EncodeToString)
|
||||
}
|
||||
|
||||
// Sha256Func contructs a function that computes the SHA256 hash of a given string
|
||||
// and encodes it with hexadecimal digits.
|
||||
var Sha256Func = makeStringHashFunction(sha256.New, hex.EncodeToString)
|
||||
|
||||
// MakeFileSha256Func constructs a function that is like Sha256Func but reads the
|
||||
// contents of a file rather than hashing a given literal string.
|
||||
func MakeFileSha256Func(baseDir string) function.Function {
|
||||
return makeFileHashFunction(baseDir, sha256.New, hex.EncodeToString)
|
||||
}
|
||||
|
||||
// Sha512Func contructs a function that computes the SHA512 hash of a given string
|
||||
// and encodes it with hexadecimal digits.
|
||||
var Sha512Func = makeStringHashFunction(sha512.New, hex.EncodeToString)
|
||||
|
||||
// MakeFileSha512Func constructs a function that is like Sha512Func but reads the
|
||||
// contents of a file rather than hashing a given literal string.
|
||||
func MakeFileSha512Func(baseDir string) function.Function {
|
||||
return makeFileHashFunction(baseDir, sha512.New, hex.EncodeToString)
|
||||
}
|
||||
|
||||
func makeStringHashFunction(hf func() hash.Hash, enc func([]byte) string) function.Function {
|
||||
return function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
|
@ -158,6 +194,30 @@ func makeStringHashFunction(hf func() hash.Hash, enc func([]byte) string) functi
|
|||
})
|
||||
}
|
||||
|
||||
func makeFileHashFunction(baseDir string, hf func() hash.Hash, enc func([]byte) string) function.Function {
|
||||
return function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
{
|
||||
Name: "path",
|
||||
Type: cty.String,
|
||||
},
|
||||
},
|
||||
Type: function.StaticReturnType(cty.String),
|
||||
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||
path := args[0].AsString()
|
||||
src, err := readFileBytes(baseDir, path)
|
||||
if err != nil {
|
||||
return cty.UnknownVal(cty.String), err
|
||||
}
|
||||
|
||||
h := hf()
|
||||
h.Write(src)
|
||||
rv := enc(h.Sum(nil))
|
||||
return cty.StringVal(rv), nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// UUID generates and returns a Type-4 UUID in the standard hexadecimal string
|
||||
// format.
|
||||
//
|
||||
|
|
|
@ -56,6 +56,51 @@ func TestBase64Sha256(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFileBase64Sha256(t *testing.T) {
|
||||
tests := []struct {
|
||||
Path cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.StringVal("testdata/hello.txt"),
|
||||
cty.StringVal("LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw=="),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/icon.png"),
|
||||
cty.StringVal("wSInO/tKEOaLGCAY2h/7gtLWMpzyLJ0ijFh95JTpYrPzXQYgviAdL9ZgpD9EAte8On+drvhFvjIFsfQUwxbNPQ=="),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/missing"),
|
||||
cty.NilVal,
|
||||
true, // no file exists
|
||||
},
|
||||
}
|
||||
|
||||
fileSHA256 := MakeFileBase64Sha512Func(".")
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("filebase64sha256(%#v)", test.Path), func(t *testing.T) {
|
||||
got, err := fileSHA256.Call([]cty.Value{test.Path})
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBase64Sha512(t *testing.T) {
|
||||
tests := []struct {
|
||||
String cty.Value
|
||||
|
@ -92,6 +137,51 @@ func TestBase64Sha512(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFileBase64Sha512(t *testing.T) {
|
||||
tests := []struct {
|
||||
Path cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.StringVal("testdata/hello.txt"),
|
||||
cty.StringVal("LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw=="),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/icon.png"),
|
||||
cty.StringVal("wSInO/tKEOaLGCAY2h/7gtLWMpzyLJ0ijFh95JTpYrPzXQYgviAdL9ZgpD9EAte8On+drvhFvjIFsfQUwxbNPQ=="),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/missing"),
|
||||
cty.NilVal,
|
||||
true, // no file exists
|
||||
},
|
||||
}
|
||||
|
||||
fileSHA512 := MakeFileBase64Sha512Func(".")
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("filebase64sha512(%#v)", test.Path), func(t *testing.T) {
|
||||
got, err := fileSHA512.Call([]cty.Value{test.Path})
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBcrypt(t *testing.T) {
|
||||
// single variable test
|
||||
p, err := Bcrypt(cty.StringVal("test"))
|
||||
|
@ -165,6 +255,51 @@ func TestMd5(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFileMD5(t *testing.T) {
|
||||
tests := []struct {
|
||||
Path cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.StringVal("testdata/hello.txt"),
|
||||
cty.StringVal("b10a8db164e0754105b7a99be72e3fe5"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/icon.png"),
|
||||
cty.StringVal("d7e6c283185a1078c58213beadca98b0"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/missing"),
|
||||
cty.NilVal,
|
||||
true, // no file exists
|
||||
},
|
||||
}
|
||||
|
||||
fileMD5 := MakeFileMd5Func(".")
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("filemd5(%#v)", test.Path), func(t *testing.T) {
|
||||
got, err := fileMD5.Call([]cty.Value{test.Path})
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRsaDecrypt(t *testing.T) {
|
||||
tests := []struct {
|
||||
Ciphertext cty.Value
|
||||
|
@ -268,6 +403,51 @@ func TestSha1(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFileSHA1(t *testing.T) {
|
||||
tests := []struct {
|
||||
Path cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.StringVal("testdata/hello.txt"),
|
||||
cty.StringVal("0a4d55a8d778e5022fab701977c5d840bbc486d0"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/icon.png"),
|
||||
cty.StringVal("2821bcc8379e1bd6f4f31b1e6a1fbb204b4a8be8"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/missing"),
|
||||
cty.NilVal,
|
||||
true, // no file exists
|
||||
},
|
||||
}
|
||||
|
||||
fileSHA1 := MakeFileSha1Func(".")
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("filesha1(%#v)", test.Path), func(t *testing.T) {
|
||||
got, err := fileSHA1.Call([]cty.Value{test.Path})
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSha256(t *testing.T) {
|
||||
tests := []struct {
|
||||
String cty.Value
|
||||
|
@ -301,6 +481,51 @@ func TestSha256(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFileSHA256(t *testing.T) {
|
||||
tests := []struct {
|
||||
Path cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.StringVal("testdata/hello.txt"),
|
||||
cty.StringVal("a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/icon.png"),
|
||||
cty.StringVal("e3b535abd2195b4f774a6033742f36d129299fcbc73ef73cb33b9dfd8ddece9a"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/missing"),
|
||||
cty.NilVal,
|
||||
true, // no file exists
|
||||
},
|
||||
}
|
||||
|
||||
fileSHA256 := MakeFileSha256Func(".")
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("filesha256(%#v)", test.Path), func(t *testing.T) {
|
||||
got, err := fileSHA256.Call([]cty.Value{test.Path})
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSha512(t *testing.T) {
|
||||
tests := []struct {
|
||||
String cty.Value
|
||||
|
@ -334,6 +559,51 @@ func TestSha512(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFileSHA512(t *testing.T) {
|
||||
tests := []struct {
|
||||
Path cty.Value
|
||||
Want cty.Value
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
cty.StringVal("testdata/hello.txt"),
|
||||
cty.StringVal("2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/icon.png"),
|
||||
cty.StringVal("c122273bfb4a10e68b182018da1ffb82d2d6329cf22c9d228c587de494e962b3f35d0620be201d2fd660a43f4402d7bc3a7f9daef845be3205b1f414c316cd3d"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
cty.StringVal("testdata/missing"),
|
||||
cty.NilVal,
|
||||
true, // no file exists
|
||||
},
|
||||
}
|
||||
|
||||
fileSHA512 := MakeFileSha512Func(".")
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("filesha512(%#v)", test.Path), func(t *testing.T) {
|
||||
got, err := fileSHA512.Call([]cty.Value{test.Path})
|
||||
|
||||
if test.Err {
|
||||
if err == nil {
|
||||
t.Fatal("succeeded; want error")
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !got.RawEquals(test.Want) {
|
||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
CipherBase64 = "eczGaDhXDbOFRZGhjx2etVzWbRqWDlmq0bvNt284JHVbwCgObiuyX9uV0LSAMY707IEgMkExJqXmsB4OWKxvB7epRB9G/3+F+pcrQpODlDuL9oDUAsa65zEpYF0Wbn7Oh7nrMQncyUPpyr9WUlALl0gRWytOA23S+y5joa4M34KFpawFgoqTu/2EEH4Xl1zo+0fy73fEto+nfkUY+meuyGZ1nUx/+DljP7ZqxHBFSlLODmtuTMdswUbHbXbWneW51D7Jm7xB8nSdiA2JQNK5+Sg5x8aNfgvFTt/m2w2+qpsyFa5Wjeu6fZmXSl840CA07aXbk9vN4I81WmJyblD/ZA=="
|
||||
PrivateKey = `
|
||||
|
|
|
@ -29,26 +29,9 @@ func MakeFileFunc(baseDir string, encBase64 bool) function.Function {
|
|||
Type: function.StaticReturnType(cty.String),
|
||||
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
|
||||
path := args[0].AsString()
|
||||
path, err := homedir.Expand(path)
|
||||
src, err := readFileBytes(baseDir, path)
|
||||
if err != nil {
|
||||
return cty.UnknownVal(cty.String), fmt.Errorf("failed to expand ~: %s", err)
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Join(baseDir, path)
|
||||
}
|
||||
|
||||
// Ensure that the path is canonical for the host OS
|
||||
path = filepath.Clean(path)
|
||||
|
||||
src, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
// ReadFile does not return Terraform-user-friendly error
|
||||
// messages, so we'll provide our own.
|
||||
if os.IsNotExist(err) {
|
||||
return cty.UnknownVal(cty.String), fmt.Errorf("no file exists at %s", path)
|
||||
}
|
||||
return cty.UnknownVal(cty.String), fmt.Errorf("failed to read %s", path)
|
||||
return cty.UnknownVal(cty.String), err
|
||||
}
|
||||
|
||||
switch {
|
||||
|
@ -270,6 +253,32 @@ var PathExpandFunc = function.New(&function.Spec{
|
|||
},
|
||||
})
|
||||
|
||||
func readFileBytes(baseDir, path string) ([]byte, error) {
|
||||
path, err := homedir.Expand(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to expand ~: %s", err)
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Join(baseDir, path)
|
||||
}
|
||||
|
||||
// Ensure that the path is canonical for the host OS
|
||||
path = filepath.Clean(path)
|
||||
|
||||
src, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
// ReadFile does not return Terraform-user-friendly error
|
||||
// messages, so we'll provide our own.
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("no file exists at %s", path)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to read %s", path)
|
||||
}
|
||||
|
||||
return src, nil
|
||||
}
|
||||
|
||||
// File reads the contents of the file at the given path.
|
||||
//
|
||||
// The file must contain valid UTF-8 bytes, or this function will return an error.
|
||||
|
|
|
@ -29,86 +29,92 @@ func (s *Scope) Functions() map[string]function.Function {
|
|||
// that would be useful to all applications using cty functions.
|
||||
|
||||
s.funcs = map[string]function.Function{
|
||||
"abs": stdlib.AbsoluteFunc,
|
||||
"basename": funcs.BasenameFunc,
|
||||
"base64decode": funcs.Base64DecodeFunc,
|
||||
"base64encode": funcs.Base64EncodeFunc,
|
||||
"base64gzip": funcs.Base64GzipFunc,
|
||||
"base64sha256": funcs.Base64Sha256Func,
|
||||
"base64sha512": funcs.Base64Sha512Func,
|
||||
"bcrypt": funcs.BcryptFunc,
|
||||
"ceil": funcs.CeilFunc,
|
||||
"chomp": funcs.ChompFunc,
|
||||
"cidrhost": funcs.CidrHostFunc,
|
||||
"cidrnetmask": funcs.CidrNetmaskFunc,
|
||||
"cidrsubnet": funcs.CidrSubnetFunc,
|
||||
"coalesce": stdlib.CoalesceFunc,
|
||||
"coalescelist": funcs.CoalesceListFunc,
|
||||
"compact": funcs.CompactFunc,
|
||||
"concat": stdlib.ConcatFunc,
|
||||
"contains": funcs.ContainsFunc,
|
||||
"csvdecode": stdlib.CSVDecodeFunc,
|
||||
"dirname": funcs.DirnameFunc,
|
||||
"distinct": funcs.DistinctFunc,
|
||||
"element": funcs.ElementFunc,
|
||||
"chunklist": funcs.ChunklistFunc,
|
||||
"file": funcs.MakeFileFunc(s.BaseDir, false),
|
||||
"fileexists": funcs.MakeFileExistsFunc(s.BaseDir),
|
||||
"filebase64": funcs.MakeFileFunc(s.BaseDir, true),
|
||||
"flatten": funcs.FlattenFunc,
|
||||
"floor": funcs.FloorFunc,
|
||||
"format": stdlib.FormatFunc,
|
||||
"formatdate": stdlib.FormatDateFunc,
|
||||
"formatlist": stdlib.FormatListFunc,
|
||||
"indent": funcs.IndentFunc,
|
||||
"index": funcs.IndexFunc,
|
||||
"join": funcs.JoinFunc,
|
||||
"jsondecode": stdlib.JSONDecodeFunc,
|
||||
"jsonencode": stdlib.JSONEncodeFunc,
|
||||
"keys": funcs.KeysFunc,
|
||||
"length": funcs.LengthFunc,
|
||||
"list": funcs.ListFunc,
|
||||
"log": funcs.LogFunc,
|
||||
"lookup": funcs.LookupFunc,
|
||||
"lower": stdlib.LowerFunc,
|
||||
"map": funcs.MapFunc,
|
||||
"matchkeys": funcs.MatchkeysFunc,
|
||||
"max": stdlib.MaxFunc,
|
||||
"md5": funcs.Md5Func,
|
||||
"merge": funcs.MergeFunc,
|
||||
"min": stdlib.MinFunc,
|
||||
"pathexpand": funcs.PathExpandFunc,
|
||||
"pow": funcs.PowFunc,
|
||||
"replace": funcs.ReplaceFunc,
|
||||
"rsadecrypt": funcs.RsaDecryptFunc,
|
||||
"sethaselement": stdlib.SetHasElementFunc,
|
||||
"setintersection": stdlib.SetIntersectionFunc,
|
||||
"setproduct": funcs.SetProductFunc,
|
||||
"setunion": stdlib.SetUnionFunc,
|
||||
"sha1": funcs.Sha1Func,
|
||||
"sha256": funcs.Sha256Func,
|
||||
"sha512": funcs.Sha512Func,
|
||||
"signum": funcs.SignumFunc,
|
||||
"slice": funcs.SliceFunc,
|
||||
"sort": funcs.SortFunc,
|
||||
"split": funcs.SplitFunc,
|
||||
"substr": stdlib.SubstrFunc,
|
||||
"timestamp": funcs.TimestampFunc,
|
||||
"timeadd": funcs.TimeAddFunc,
|
||||
"title": funcs.TitleFunc,
|
||||
"tostring": funcs.MakeToFunc(cty.String),
|
||||
"tonumber": funcs.MakeToFunc(cty.Number),
|
||||
"tobool": funcs.MakeToFunc(cty.Bool),
|
||||
"toset": funcs.MakeToFunc(cty.Set(cty.DynamicPseudoType)),
|
||||
"tolist": funcs.MakeToFunc(cty.List(cty.DynamicPseudoType)),
|
||||
"tomap": funcs.MakeToFunc(cty.Map(cty.DynamicPseudoType)),
|
||||
"transpose": funcs.TransposeFunc,
|
||||
"trimspace": funcs.TrimSpaceFunc,
|
||||
"upper": stdlib.UpperFunc,
|
||||
"urlencode": funcs.URLEncodeFunc,
|
||||
"uuid": funcs.UUIDFunc,
|
||||
"values": funcs.ValuesFunc,
|
||||
"zipmap": funcs.ZipmapFunc,
|
||||
"abs": stdlib.AbsoluteFunc,
|
||||
"basename": funcs.BasenameFunc,
|
||||
"base64decode": funcs.Base64DecodeFunc,
|
||||
"base64encode": funcs.Base64EncodeFunc,
|
||||
"base64gzip": funcs.Base64GzipFunc,
|
||||
"base64sha256": funcs.Base64Sha256Func,
|
||||
"base64sha512": funcs.Base64Sha512Func,
|
||||
"bcrypt": funcs.BcryptFunc,
|
||||
"ceil": funcs.CeilFunc,
|
||||
"chomp": funcs.ChompFunc,
|
||||
"cidrhost": funcs.CidrHostFunc,
|
||||
"cidrnetmask": funcs.CidrNetmaskFunc,
|
||||
"cidrsubnet": funcs.CidrSubnetFunc,
|
||||
"coalesce": stdlib.CoalesceFunc,
|
||||
"coalescelist": funcs.CoalesceListFunc,
|
||||
"compact": funcs.CompactFunc,
|
||||
"concat": stdlib.ConcatFunc,
|
||||
"contains": funcs.ContainsFunc,
|
||||
"csvdecode": stdlib.CSVDecodeFunc,
|
||||
"dirname": funcs.DirnameFunc,
|
||||
"distinct": funcs.DistinctFunc,
|
||||
"element": funcs.ElementFunc,
|
||||
"chunklist": funcs.ChunklistFunc,
|
||||
"file": funcs.MakeFileFunc(s.BaseDir, false),
|
||||
"fileexists": funcs.MakeFileExistsFunc(s.BaseDir),
|
||||
"filebase64": funcs.MakeFileFunc(s.BaseDir, true),
|
||||
"filebase64sha256": funcs.MakeFileBase64Sha256Func(s.BaseDir),
|
||||
"filebase64sha512": funcs.MakeFileBase64Sha512Func(s.BaseDir),
|
||||
"filemd5": funcs.MakeFileMd5Func(s.BaseDir),
|
||||
"filesha1": funcs.MakeFileSha1Func(s.BaseDir),
|
||||
"filesha256": funcs.MakeFileSha256Func(s.BaseDir),
|
||||
"filesha512": funcs.MakeFileSha512Func(s.BaseDir),
|
||||
"flatten": funcs.FlattenFunc,
|
||||
"floor": funcs.FloorFunc,
|
||||
"format": stdlib.FormatFunc,
|
||||
"formatdate": stdlib.FormatDateFunc,
|
||||
"formatlist": stdlib.FormatListFunc,
|
||||
"indent": funcs.IndentFunc,
|
||||
"index": funcs.IndexFunc,
|
||||
"join": funcs.JoinFunc,
|
||||
"jsondecode": stdlib.JSONDecodeFunc,
|
||||
"jsonencode": stdlib.JSONEncodeFunc,
|
||||
"keys": funcs.KeysFunc,
|
||||
"length": funcs.LengthFunc,
|
||||
"list": funcs.ListFunc,
|
||||
"log": funcs.LogFunc,
|
||||
"lookup": funcs.LookupFunc,
|
||||
"lower": stdlib.LowerFunc,
|
||||
"map": funcs.MapFunc,
|
||||
"matchkeys": funcs.MatchkeysFunc,
|
||||
"max": stdlib.MaxFunc,
|
||||
"md5": funcs.Md5Func,
|
||||
"merge": funcs.MergeFunc,
|
||||
"min": stdlib.MinFunc,
|
||||
"pathexpand": funcs.PathExpandFunc,
|
||||
"pow": funcs.PowFunc,
|
||||
"replace": funcs.ReplaceFunc,
|
||||
"rsadecrypt": funcs.RsaDecryptFunc,
|
||||
"sethaselement": stdlib.SetHasElementFunc,
|
||||
"setintersection": stdlib.SetIntersectionFunc,
|
||||
"setproduct": funcs.SetProductFunc,
|
||||
"setunion": stdlib.SetUnionFunc,
|
||||
"sha1": funcs.Sha1Func,
|
||||
"sha256": funcs.Sha256Func,
|
||||
"sha512": funcs.Sha512Func,
|
||||
"signum": funcs.SignumFunc,
|
||||
"slice": funcs.SliceFunc,
|
||||
"sort": funcs.SortFunc,
|
||||
"split": funcs.SplitFunc,
|
||||
"substr": stdlib.SubstrFunc,
|
||||
"timestamp": funcs.TimestampFunc,
|
||||
"timeadd": funcs.TimeAddFunc,
|
||||
"title": funcs.TitleFunc,
|
||||
"tostring": funcs.MakeToFunc(cty.String),
|
||||
"tonumber": funcs.MakeToFunc(cty.Number),
|
||||
"tobool": funcs.MakeToFunc(cty.Bool),
|
||||
"toset": funcs.MakeToFunc(cty.Set(cty.DynamicPseudoType)),
|
||||
"tolist": funcs.MakeToFunc(cty.List(cty.DynamicPseudoType)),
|
||||
"tomap": funcs.MakeToFunc(cty.Map(cty.DynamicPseudoType)),
|
||||
"transpose": funcs.TransposeFunc,
|
||||
"trimspace": funcs.TrimSpaceFunc,
|
||||
"upper": stdlib.UpperFunc,
|
||||
"urlencode": funcs.URLEncodeFunc,
|
||||
"uuid": funcs.UUIDFunc,
|
||||
"values": funcs.ValuesFunc,
|
||||
"zipmap": funcs.ZipmapFunc,
|
||||
}
|
||||
|
||||
s.funcs["templatefile"] = funcs.MakeTemplateFileFunc(s.BaseDir, func() map[string]function.Function {
|
||||
|
|
|
@ -27,5 +27,7 @@ uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek=
|
|||
|
||||
## Related Functions
|
||||
|
||||
* [`filebase64sha256`](./filebase64sha256.html) calculates the same hash from
|
||||
the contents of a file rather than from a string value.
|
||||
* [`sha256`](./sha256.html) calculates the same hash but returns the result
|
||||
in a more-verbose hexadecimal encoding.
|
||||
|
|
|
@ -27,5 +27,7 @@ MJ7MSJwS1utMxA9QyQLytNDtd+5RGnx6m808qG1M2G+YndNbxf9JlnDaNCVbRbDP2DDoH2Bdz33FVC6T
|
|||
|
||||
## Related Functions
|
||||
|
||||
* [`filebase64sha512`](./filebase64sha512.html) calculates the same hash from
|
||||
the contents of a file rather than from a string value.
|
||||
* [`sha512`](./sha512.html) calculates the same hash but returns the result
|
||||
in a more-verbose hexadecimal encoding.
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "filebase64sha256 - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-crypto-filebase64sha256"
|
||||
description: |-
|
||||
The filebase64sha256 function computes the SHA256 hash of the contents of
|
||||
a given file and encodes it with Base64.
|
||||
---
|
||||
|
||||
# `filebase64sha256` Function
|
||||
|
||||
`filebase64sha256` is a variant of [`base64sha256`](./base64sha256.html)
|
||||
that hashes the contents of a given file rather than a literal string.
|
||||
|
||||
This is similar to `base64sha256(file(filename))`, but
|
||||
because [`file`](./file.html) accepts only UTF-8 text it cannot be used to
|
||||
create hashes for binary files.
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "filebase64sha512 - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-crypto-filebase64sha512"
|
||||
description: |-
|
||||
The filebase64sha512 function computes the SHA512 hash of the contents of
|
||||
a given file and encodes it with Base64.
|
||||
---
|
||||
|
||||
# `filebase64sha512` Function
|
||||
|
||||
`filebase64sha512` is a variant of [`base64sha512`](./base64sha512.html)
|
||||
that hashes the contents of a given file rather than a literal string.
|
||||
|
||||
This is similar to `base64sha512(file(filename))`, but
|
||||
because [`file`](./file.html) accepts only UTF-8 text it cannot be used to
|
||||
create hashes for binary files.
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "filemd5 - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-crypto-filemd5"
|
||||
description: |-
|
||||
The filemd5 function computes the MD5 hash of the contents of
|
||||
a given file and encodes it as hex.
|
||||
---
|
||||
|
||||
# `filemd5` Function
|
||||
|
||||
`filemd5` is a variant of [`md5`](./md5.html)
|
||||
that hashes the contents of a given file rather than a literal string.
|
||||
|
||||
This is similar to `md5(file(filename))`, but
|
||||
because [`file`](./file.html) accepts only UTF-8 text it cannot be used to
|
||||
create hashes for binary files.
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "filesha1 - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-crypto-filesha1"
|
||||
description: |-
|
||||
The filesha1 function computes the SHA1 hash of the contents of
|
||||
a given file and encodes it as hex.
|
||||
---
|
||||
|
||||
# `filesha1` Function
|
||||
|
||||
`filesha1` is a variant of [`sha1`](./sha1.html)
|
||||
that hashes the contents of a given file rather than a literal string.
|
||||
|
||||
This is similar to `sha1(file(filename))`, but
|
||||
because [`file`](./file.html) accepts only UTF-8 text it cannot be used to
|
||||
create hashes for binary files.
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "filesha256 - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-crypto-filesha256"
|
||||
description: |-
|
||||
The filesha256 function computes the SHA256 hash of the contents of
|
||||
a given file and encodes it as hex.
|
||||
---
|
||||
|
||||
# `filesha256` Function
|
||||
|
||||
`filesha256` is a variant of [`sha256`](./sha256.html)
|
||||
that hashes the contents of a given file rather than a literal string.
|
||||
|
||||
This is similar to `sha256(file(filename))`, but
|
||||
because [`file`](./file.html) accepts only UTF-8 text it cannot be used to
|
||||
create hashes for binary files.
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
layout: "functions"
|
||||
page_title: "filesha512 - Functions - Configuration Language"
|
||||
sidebar_current: "docs-funcs-crypto-filesha512"
|
||||
description: |-
|
||||
The filesha512 function computes the SHA512 hash of the contents of
|
||||
a given file and encodes it as hex.
|
||||
---
|
||||
|
||||
# `filesha512` Function
|
||||
|
||||
`filesha512` is a variant of [`sha512`](./sha512.html)
|
||||
that hashes the contents of a given file rather than a literal string.
|
||||
|
||||
This is similar to `sha512(file(filename))`, but
|
||||
because [`file`](./file.html) accepts only UTF-8 text it cannot be used to
|
||||
create hashes for binary files.
|
|
@ -26,3 +26,8 @@ considerations applying to the MD5 algorithm.
|
|||
> md5("hello world")
|
||||
5eb63bbbe01eeed093cb22bb8f5acdc3
|
||||
```
|
||||
|
||||
## Related Functions
|
||||
|
||||
* [`filemd5`](./filemd5.html) calculates the same hash from
|
||||
the contents of a file rather than from a string value.
|
||||
|
|
|
@ -26,3 +26,8 @@ relevant literature to understand the security implications.
|
|||
> sha1("hello world")
|
||||
2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
```
|
||||
|
||||
## Related Functions
|
||||
|
||||
* [`filesha1`](./filesha1.html) calculates the same hash from
|
||||
the contents of a file rather than from a string value.
|
||||
|
|
|
@ -25,5 +25,10 @@ b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
|||
|
||||
## Related Functions
|
||||
|
||||
|
||||
## Related Functions
|
||||
|
||||
* [`filesha256`](./filesha256.html) calculates the same hash from
|
||||
the contents of a file rather than from a string value.
|
||||
* [`base64sha256`](./base64sha256.html) calculates the same hash but returns
|
||||
the result in a more-compact Base64 encoding.
|
||||
|
|
|
@ -25,5 +25,7 @@ then encoded to lowercase hexadecimal digits before returning.
|
|||
|
||||
## Related Functions
|
||||
|
||||
* [`filesha512`](./filesha512.html) calculates the same hash from
|
||||
the contents of a file rather than from a string value.
|
||||
* [`base64sha512`](./base64sha512.html) calculates the same hash but returns
|
||||
the result in a more-compact Base64 encoding.
|
||||
|
|
|
@ -311,6 +311,30 @@
|
|||
<a href="/docs/configuration/functions/bcrypt.html">bcrypt</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-funcs-crypto-filebase64sha256") %>>
|
||||
<a href="/docs/configuration/functions/filebase64sha256.html">filebase64sha256</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-funcs-crypto-filebase64sha512") %>>
|
||||
<a href="/docs/configuration/functions/filebase64sha512.html">filebase64sha512</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-funcs-crypto-filemd5") %>>
|
||||
<a href="/docs/configuration/functions/filemd5.html">filemd5</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-funcs-crypto-filesha1") %>>
|
||||
<a href="/docs/configuration/functions/filesha1.html">filesha1</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-funcs-crypto-filesha256") %>>
|
||||
<a href="/docs/configuration/functions/filesha256.html">filesha256</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-funcs-crypto-filesha512") %>>
|
||||
<a href="/docs/configuration/functions/filesha512.html">filesha512</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-funcs-crypto-md5") %>>
|
||||
<a href="/docs/configuration/functions/md5.html">md5</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue