mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-05 20:40:16 -08:00
Co-authored-by: knqyf263 <knqyf263@users.noreply.github.com> Co-authored-by: nikpivkin <nikita.pivkin@smartforce.io>
341 lines
6.5 KiB
Go
341 lines
6.5 KiB
Go
package azure
|
|
|
|
import (
|
|
"encoding/json/jsontext"
|
|
"encoding/json/v2"
|
|
"fmt"
|
|
"maps"
|
|
"slices"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/samber/lo"
|
|
|
|
"github.com/aquasecurity/trivy/pkg/iac/types"
|
|
)
|
|
|
|
type EvalContext struct{}
|
|
|
|
type Kind string
|
|
|
|
const (
|
|
KindUnresolvable Kind = "unresolvable"
|
|
KindNull Kind = "null"
|
|
KindBoolean Kind = "boolean"
|
|
KindString Kind = "string"
|
|
KindNumber Kind = "number"
|
|
KindObject Kind = "object"
|
|
KindArray Kind = "array"
|
|
KindExpression Kind = "expression"
|
|
)
|
|
|
|
type Value struct {
|
|
metadata *types.Metadata
|
|
rLit any
|
|
rMap map[string]Value
|
|
rArr []Value
|
|
Kind Kind
|
|
Comments []string
|
|
}
|
|
|
|
var NullValue = Value{
|
|
Kind: KindNull,
|
|
}
|
|
|
|
func NewValue(value any, metadata types.Metadata) Value {
|
|
|
|
v := Value{
|
|
metadata: &metadata,
|
|
}
|
|
|
|
switch ty := value.(type) {
|
|
case []any:
|
|
v.Kind = KindArray
|
|
for _, child := range ty {
|
|
if internal, ok := child.(Value); ok {
|
|
v.rArr = append(v.rArr, internal)
|
|
} else {
|
|
v.rArr = append(v.rArr, NewValue(child, metadata))
|
|
}
|
|
}
|
|
case []Value:
|
|
v.Kind = KindArray
|
|
v.rArr = append(v.rArr, ty...)
|
|
|
|
case map[string]any:
|
|
v.Kind = KindObject
|
|
v.rMap = make(map[string]Value)
|
|
for key, val := range ty {
|
|
if internal, ok := val.(Value); ok {
|
|
v.rMap[key] = internal
|
|
} else {
|
|
v.rMap[key] = NewValue(val, metadata)
|
|
}
|
|
}
|
|
case map[string]Value:
|
|
v.Kind = KindObject
|
|
v.rMap = make(map[string]Value)
|
|
maps.Copy(v.rMap, ty)
|
|
case string:
|
|
v.Kind = KindString
|
|
v.rLit = ty
|
|
case int, int64, int32, float32, float64, int8, int16, uint8, uint16, uint32, uint64:
|
|
v.Kind = KindNumber
|
|
v.rLit = ty
|
|
case bool:
|
|
v.Kind = KindBoolean
|
|
v.rLit = ty
|
|
case nil:
|
|
v.Kind = KindNull
|
|
v.rLit = ty
|
|
default:
|
|
v.Kind = KindUnresolvable
|
|
v.rLit = ty
|
|
}
|
|
|
|
return v
|
|
}
|
|
|
|
func NewExprValue(value string, metadata types.Metadata) Value {
|
|
return Value{
|
|
metadata: &metadata,
|
|
Kind: KindExpression,
|
|
rLit: value,
|
|
}
|
|
}
|
|
|
|
func (v *Value) GetMetadata() types.Metadata {
|
|
return lo.FromPtr(v.metadata)
|
|
}
|
|
|
|
func (v *Value) SetMetadata(m *types.Metadata) {
|
|
v.metadata = m
|
|
}
|
|
|
|
func (v *Value) UnmarshalJSONFrom(dec *jsontext.Decoder) error {
|
|
switch k := dec.PeekKind(); k {
|
|
case 't', 'f':
|
|
v.Kind = KindBoolean
|
|
if err := json.UnmarshalDecode(dec, &v.rLit); err != nil {
|
|
return err
|
|
}
|
|
case '"':
|
|
var s string
|
|
if err := json.UnmarshalDecode(dec, &s); err != nil {
|
|
return err
|
|
}
|
|
if strings.HasPrefix(s, "[") && !strings.HasPrefix(s, "[[") && strings.HasSuffix(s, "]") {
|
|
v.Kind = KindExpression
|
|
v.rLit = s[1 : len(s)-1]
|
|
} else {
|
|
v.Kind = KindString
|
|
v.rLit = s
|
|
}
|
|
case '0':
|
|
v.Kind = KindNumber
|
|
if err := json.UnmarshalDecode(dec, &v.rLit); err != nil {
|
|
return err
|
|
}
|
|
if f, ok := v.rLit.(float64); ok {
|
|
if i := int64(f); float64(i) == f {
|
|
v.rLit = i
|
|
}
|
|
}
|
|
case '[':
|
|
v.Kind = KindArray
|
|
if err := json.UnmarshalDecode(dec, &v.rArr); err != nil {
|
|
return err
|
|
}
|
|
case '{':
|
|
v.Kind = KindObject
|
|
if err := json.UnmarshalDecode(dec, &v.rMap); err != nil {
|
|
return err
|
|
}
|
|
case 'n':
|
|
// TODO: UnmarshalJSONFrom is called only for the root null
|
|
return dec.SkipValue()
|
|
case 0:
|
|
return dec.SkipValue()
|
|
default:
|
|
return fmt.Errorf("unexpected token kind %q at %d", k.String(), dec.InputOffset())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v Value) AsString() string {
|
|
v.Resolve()
|
|
|
|
if v.Kind != KindString {
|
|
return ""
|
|
}
|
|
|
|
return v.rLit.(string)
|
|
}
|
|
|
|
func (v Value) AsBool() bool {
|
|
v.Resolve()
|
|
if v.Kind != KindBoolean {
|
|
return false
|
|
}
|
|
return v.rLit.(bool)
|
|
}
|
|
|
|
func (v Value) AsInt() int {
|
|
v.Resolve()
|
|
if v.Kind != KindNumber {
|
|
return 0
|
|
}
|
|
return int(v.rLit.(int64))
|
|
}
|
|
|
|
func (v Value) AsFloat() float64 {
|
|
v.Resolve()
|
|
if v.Kind != KindNumber {
|
|
return 0
|
|
}
|
|
return v.rLit.(float64)
|
|
}
|
|
|
|
func (v Value) AsIntValue(defaultValue int, metadata types.Metadata) types.IntValue {
|
|
v.Resolve()
|
|
if v.Kind != KindNumber {
|
|
return types.Int(defaultValue, metadata)
|
|
}
|
|
return types.Int(v.AsInt(), metadata)
|
|
}
|
|
|
|
func (v Value) AsBoolValue(defaultValue bool, metadata types.Metadata) types.BoolValue {
|
|
v.Resolve()
|
|
if v.Kind == KindString {
|
|
possibleValue := strings.ToLower(v.rLit.(string))
|
|
if slices.Contains([]string{
|
|
"true",
|
|
"1",
|
|
"yes",
|
|
"on",
|
|
"enabled",
|
|
}, possibleValue) {
|
|
return types.Bool(true, metadata)
|
|
}
|
|
}
|
|
|
|
if v.Kind != KindBoolean {
|
|
return types.Bool(defaultValue, metadata)
|
|
}
|
|
|
|
return types.Bool(v.rLit.(bool), v.GetMetadata())
|
|
}
|
|
|
|
func (v Value) EqualTo(value any) bool {
|
|
switch ty := value.(type) {
|
|
case string:
|
|
return v.AsString() == ty
|
|
default:
|
|
panic("not supported")
|
|
}
|
|
}
|
|
|
|
func (v Value) AsStringValue(defaultValue string, metadata types.Metadata) types.StringValue {
|
|
v.Resolve()
|
|
if v.Kind != KindString {
|
|
return types.StringDefault(defaultValue, metadata)
|
|
}
|
|
return types.String(v.rLit.(string), v.GetMetadata())
|
|
}
|
|
|
|
func (v Value) GetMapValue(key string) Value {
|
|
v.Resolve()
|
|
if v.Kind != KindObject {
|
|
return NullValue
|
|
}
|
|
v, exists := v.rMap[key]
|
|
if !exists {
|
|
return NullValue
|
|
}
|
|
return v
|
|
}
|
|
|
|
func (v Value) AsMap() map[string]Value {
|
|
v.Resolve()
|
|
if v.Kind != KindObject {
|
|
return nil
|
|
}
|
|
return v.rMap
|
|
}
|
|
|
|
func (v Value) AsList() []Value {
|
|
v.Resolve()
|
|
if v.Kind != KindArray {
|
|
return nil
|
|
}
|
|
return v.rArr
|
|
}
|
|
|
|
func (v Value) Raw() any {
|
|
switch v.Kind {
|
|
case KindArray:
|
|
// TODO: recursively build raw array
|
|
return nil
|
|
case KindObject:
|
|
// TODO: recursively build raw object
|
|
return nil
|
|
default:
|
|
return v.rLit
|
|
}
|
|
}
|
|
|
|
func (v *Value) Resolve() {
|
|
if v.Kind != KindExpression {
|
|
return
|
|
}
|
|
// if resolver, ok := v.Metadata.Internal().(Resolver); ok {
|
|
// *v = resolver.ResolveExpression(*v)
|
|
// }
|
|
}
|
|
|
|
func (v Value) HasKey(key string) bool {
|
|
v.Resolve()
|
|
_, ok := v.rMap[key]
|
|
return ok
|
|
}
|
|
|
|
func (v Value) AsTimeValue(parentMeta types.Metadata) types.TimeValue {
|
|
v.Resolve()
|
|
|
|
switch v.Kind {
|
|
case KindString:
|
|
t, err := time.Parse(time.RFC3339, v.rLit.(string))
|
|
if err != nil {
|
|
return types.Time(time.Time{}, parentMeta)
|
|
}
|
|
return types.Time(t, v.GetMetadata())
|
|
case KindNumber:
|
|
var tv int64
|
|
switch vv := v.rLit.(type) {
|
|
case float64:
|
|
tv = int64(vv)
|
|
case int64:
|
|
tv = vv
|
|
}
|
|
return types.Time(time.Unix(tv, 0), v.GetMetadata())
|
|
default:
|
|
return types.Time(time.Time{}, parentMeta)
|
|
}
|
|
}
|
|
|
|
func (v Value) AsStringValuesList(defaultValue string) (stringValues []types.StringValue) {
|
|
v.Resolve()
|
|
if v.Kind != KindArray {
|
|
return
|
|
}
|
|
for _, item := range v.rArr {
|
|
stringValues = append(stringValues, item.AsStringValue(defaultValue, item.GetMetadata()))
|
|
}
|
|
|
|
return stringValues
|
|
}
|
|
|
|
func (v Value) IsNull() bool {
|
|
return v.Kind == KindNull
|
|
}
|