Files
releases/bundle/hash_test.go
T
Ashutosh Narkar 338583c18a Add support for OPA bundle signatures
These changes add support for digital signatures for policy bundles which
can be used to verify their authenticity.

Bundle signature verification involves the following steps:

* Verify the JWT signature
* Verify the files in the JWT payload exist in the bundle
* Verify the file content of the files in bundle match with those in the payload

This commit adds a new `sign` command to generate a digital signature for policy bundles.

For more details, run "opa sign --help"

The signatures generated by the 'sign' command can be verified by the
'build' command. The 'build' command can also sign the bundle it generates.

The 'run' command can verify a signed bundle or skip verification altogether.

OPA 'sign', 'build' and 'run' can be used to
sign/verify bundles in bundle mode (--bundle) mode only. Verification
can be also be performed when bundle downloading is enabled.

Fixes: #1757

Signed-off-by: Ashutosh Narkar <anarkar4387@gmail.com>
2020-07-14 09:49:59 -04:00

124 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2020 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package bundle
import (
"bytes"
"encoding/json"
"testing"
)
func TestHashFile(t *testing.T) {
mapInput := map[string]interface{}{
"key1": []interface{}{
"element1",
"element2",
},
"key2": map[string]interface{}{
"a": 0,
"b": 1,
"c": json.Number("123.45678911111111111111111111111111111111111111111111111"),
},
}
arrayInput := []interface{}{
[]string{"foo", "bar"},
mapInput,
`package example`,
[]string{"$", "α", "©", "™"},
}
tests := map[string]struct {
input interface{}
algorithm HashingAlgorithm
}{
"map": {mapInput, SHA256},
"array": {arrayInput, MD5},
"string": {"abc", SHA256},
"string_with_html_chars": {"<foo></foo>", SHA256},
"null": {`null`, SHA512},
"bool": {false, SHA256},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
h, _ := NewSignatureHasher(tc.algorithm)
// compute hash from the raw bytes
a := encodePrimitive(tc.input)
hash := h.(*hasher).h()
hash.Write(a)
d1 := hash.Sum(nil)
// compute hash on the input
d2, err := h.(*hasher).HashFile(tc.input)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if !bytes.Equal(d1, d2) {
t.Fatalf("Digests are not equal. Expected: %x but got: %x", d1, d2)
}
})
}
}
func TestHashFileBytes(t *testing.T) {
mapInput := map[string]interface{}{
"key1": []interface{}{
"element1",
"element2",
},
"key2": map[string]interface{}{
"a": 0,
"b": 1,
"c": json.Number("123.45678911111111111111111111111111111111111111111111111"),
},
}
arrayInput := []interface{}{
[]string{"foo", "bar"},
mapInput,
`package example`,
[]string{"$", "α", "©", "™"},
}
arrayBytes, _ := json.Marshal(arrayInput)
mapBytes, _ := json.Marshal(mapInput)
tests := map[string]struct {
input []byte
algorithm HashingAlgorithm
}{
"map_byte_array": {mapBytes, SHA256},
"array_byte_array": {arrayBytes, MD5},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
h, _ := NewSignatureHasher(tc.algorithm)
// compute hash from the raw bytes
hash := h.(*hasher).h()
hash.Write(tc.input)
d1 := hash.Sum(nil)
// compute hash on the input
d2, err := h.(*hasher).HashFile(tc.input)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if !bytes.Equal(d1, d2) {
t.Fatalf("Digests are not equal. Expected: %x but got: %x", d1, d2)
}
})
}
}