mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-21 23:00:42 -08:00
179 lines
3.0 KiB
Go
179 lines
3.0 KiB
Go
package terraform
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
type Reference struct {
|
|
blockType Type
|
|
typeLabel string
|
|
nameLabel string
|
|
remainder []string
|
|
key cty.Value
|
|
parent string
|
|
}
|
|
|
|
func extendReference(ref Reference, name string) Reference {
|
|
child := ref
|
|
child.remainder = make([]string, len(ref.remainder))
|
|
if len(ref.remainder) > 0 {
|
|
copy(child.remainder, ref.remainder)
|
|
}
|
|
child.remainder = append(child.remainder, name)
|
|
return child
|
|
}
|
|
|
|
func newReference(parts []string, parentKey string) (*Reference, error) {
|
|
|
|
var ref Reference
|
|
|
|
if len(parts) == 0 {
|
|
return nil, errors.New("cannot create empty reference")
|
|
}
|
|
|
|
blockType, err := TypeFromRefName(parts[0])
|
|
if err != nil {
|
|
blockType = &TypeResource
|
|
}
|
|
|
|
ref.blockType = *blockType
|
|
|
|
if ref.blockType.removeTypeInReference && parts[0] != blockType.name {
|
|
ref.typeLabel = parts[0]
|
|
if len(parts) > 1 {
|
|
ref.nameLabel = parts[1]
|
|
}
|
|
} else if len(parts) > 1 {
|
|
ref.typeLabel = parts[1]
|
|
if len(parts) > 2 {
|
|
ref.nameLabel = parts[2]
|
|
} else {
|
|
ref.nameLabel = ref.typeLabel
|
|
ref.typeLabel = ""
|
|
}
|
|
}
|
|
if len(parts) > 3 {
|
|
ref.remainder = parts[3:]
|
|
}
|
|
|
|
if parentKey != "root" {
|
|
ref.parent = parentKey
|
|
}
|
|
|
|
return &ref, nil
|
|
}
|
|
|
|
func (r Reference) BlockType() Type {
|
|
return r.blockType
|
|
}
|
|
|
|
func (r Reference) TypeLabel() string {
|
|
return r.typeLabel
|
|
}
|
|
|
|
func (r Reference) NameLabel() string {
|
|
return r.nameLabel
|
|
}
|
|
|
|
func (r Reference) HumanReadable() string {
|
|
if r.parent == "" {
|
|
return r.String()
|
|
}
|
|
return fmt.Sprintf("%s:%s", r.parent, r.String())
|
|
}
|
|
|
|
func (r Reference) LogicalID() string {
|
|
return r.String()
|
|
}
|
|
|
|
func (r Reference) String() string {
|
|
|
|
base := r.typeLabel
|
|
if r.nameLabel != "" {
|
|
base = fmt.Sprintf("%s.%s", base, r.nameLabel)
|
|
}
|
|
|
|
if !r.blockType.removeTypeInReference {
|
|
base = r.blockType.Name()
|
|
if r.typeLabel != "" {
|
|
base += "." + r.typeLabel
|
|
}
|
|
if r.nameLabel != "" {
|
|
base += "." + r.nameLabel
|
|
}
|
|
}
|
|
|
|
base += r.KeyBracketed()
|
|
|
|
for _, rem := range r.remainder {
|
|
base += "." + rem
|
|
}
|
|
|
|
return base
|
|
}
|
|
|
|
func (r Reference) RefersTo(other Reference) bool {
|
|
|
|
if r.BlockType() != other.BlockType() {
|
|
return false
|
|
}
|
|
if r.TypeLabel() != other.TypeLabel() {
|
|
return false
|
|
}
|
|
if r.NameLabel() != other.NameLabel() {
|
|
return false
|
|
}
|
|
if (r.Key() != "" || other.Key() != "") && r.Key() != other.Key() {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (r *Reference) SetKey(key cty.Value) {
|
|
if key.IsNull() || !key.IsKnown() {
|
|
return
|
|
}
|
|
r.key = key
|
|
}
|
|
|
|
func (r Reference) KeyBracketed() string {
|
|
switch v := key(r).(type) {
|
|
case int:
|
|
return fmt.Sprintf("[%d]", v)
|
|
case string:
|
|
if v == "" {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("[%q]", v)
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func (r Reference) RawKey() cty.Value {
|
|
return r.key
|
|
}
|
|
|
|
func (r Reference) Key() string {
|
|
return fmt.Sprintf("%v", key(r))
|
|
}
|
|
|
|
func key(r Reference) any {
|
|
if r.key.IsNull() || !r.key.IsKnown() {
|
|
return ""
|
|
}
|
|
switch r.key.Type() {
|
|
case cty.Number:
|
|
f := r.key.AsBigFloat()
|
|
f64, _ := f.Float64()
|
|
return int(f64)
|
|
case cty.String:
|
|
return r.key.AsString()
|
|
default:
|
|
return ""
|
|
}
|
|
}
|