/
headersha256.go
74 lines (60 loc) · 1.72 KB
/
headersha256.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package auth
import (
"crypto/sha256"
"encoding/hex"
"net/http"
"github.com/zalando/skipper/predicates"
"github.com/zalando/skipper/routing"
)
type headerSha256Spec struct{}
type headerSha256Predicate struct {
name string
hashes [][sha256.Size]byte
}
// NewHeaderSHA256 creates a predicate specification, whose instances match SHA-256 hash of the header value.
// The HeaderSHA256 predicate requires the header name and one or more hex-encoded SHA-256 hash values of the matching header.
func NewHeaderSHA256() routing.PredicateSpec {
return &headerSha256Spec{}
}
func (*headerSha256Spec) Name() string {
return predicates.HeaderSHA256Name
}
// Create a predicate instance matching SHA256 hash of the header value
func (*headerSha256Spec) Create(args []interface{}) (routing.Predicate, error) {
if len(args) < 2 {
return nil, predicates.ErrInvalidPredicateParameters
}
name, ok := args[0].(string)
if !ok {
return nil, predicates.ErrInvalidPredicateParameters
}
var hashes [][sha256.Size]byte
for _, arg := range args[1:] {
hexHash, ok := arg.(string)
if !ok {
return nil, predicates.ErrInvalidPredicateParameters
}
hash, err := hex.DecodeString(hexHash)
if err != nil {
return nil, err
}
if len(hash) != sha256.Size {
return nil, predicates.ErrInvalidPredicateParameters
}
hashes = append(hashes, *(*[sha256.Size]byte)(hash)) // https://github.com/golang/go/issues/46505
}
return &headerSha256Predicate{name, hashes}, nil
}
func (p *headerSha256Predicate) Match(r *http.Request) bool {
value := r.Header.Get(p.name)
if value == "" {
return false
}
valueHash := sha256.Sum256([]byte(value))
for _, hash := range p.hashes {
if valueHash == hash {
return true
}
}
return false
}