代码之家  ›  专栏  ›  技术社区  ›  tommy_o

反汇编AWS IAM文档,但文档中有条件字符串或[]字符串

  •  0
  • tommy_o  · 技术社区  · 7 年前

    我正在执行IAM政策 examples 对于AWS Go SDK,尝试执行与 Create Policy 示例——基本上,获取帐户中的所有IAM策略,获取默认策略版本,然后将json文档解组到结构中,以便轻松解析。

    我已经完成了这一步,但我一直在研究go如何处理条件结构类型。在AWS策略文档版本响应中 StatementEntry 可以是 string []string 取决于文件。

    最佳做法是什么?是否在错误处理中添加另一个结构并使用重试逻辑?

    package main
    
    import (
        "encoding/json"
        "fmt"
        "github.com/aws/aws-sdk-go/aws"
        "github.com/aws/aws-sdk-go/aws/session"
        "github.com/aws/aws-sdk-go/service/iam"
        "log"
        "net/url"
    )
    
    type PolicyDocument struct {
        Version   string
        Statement []StatementEntry
    }
    
    type StatementEntry struct {
        Effect   string
        Action   []string
        Resource []string
    }
    
    func main() {
        sess, _ := session.NewSession(&aws.Config{
            Region: aws.String("us-west-2")},
        )
    
        svc := iam.New(sess)
    
        fmt.Printf("%s - %s\n", arn, *result.Policy.Description)
    
        results, _ := svc.ListPolicies(&iam.ListPoliciesInput{})
    
        for _, policy := range results.Policies {
    
            arn := policy.Arn
            version := policy.DefaultVersionId
    
            pv, _ := svc.GetPolicyVersion(&iam.GetPolicyVersionInput{
                PolicyArn: arn,
                VersionId: version,
            })
    
            decodedValue, err := url.QueryUnescape(aws.StringValue(pv.PolicyVersion.Document))
            if err != nil {
                log.Fatal(err)
                return
            }
            //fmt.Println(decodedValue)
    
            data := []byte(decodedValue)
    
            var doc PolicyDocument
            err1 := json.Unmarshal(data, &doc)
    
            if err1 != nil {
                log.Fatal(err1)
            }
    
            fmt.Printf("\n----\n%v\n---\n", doc)
        }
    }
    

    实例 PolicyDocuments 这是:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "ssm:PutParameter",
                    "ssm:DeleteParameter",
                    "ssm:DescribeInstancePatchStates",
                    "elasticloadbalancing:RegisterTargets",
                    "elasticloadbalancing:DescribeTargetHealth",
                    "elasticloadbalancing:DescribeTargetGroups",
                    "elasticloadbalancing:DeregisterTargets",
                    "ssm:GetParameter"
                ],
                "Resource": "*"
            }
        ]
    }
    

    还有这个 Resource []string 语句条目 ):

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "s3:ListBucket"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::SageMaker"
                ]
            },
            {
                "Action": [
                    "s3:GetObject",
                    "s3:PutObject",
                    "s3:DeleteObject"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::SageMaker/*"
                ]
            }
        ]
    }
    
    0 回复  |  直到 7 年前
        1
  •  3
  •   Iain Duncan pujaji    7 年前

    可以通过使用切片的自定义类型和解组方法来实现这一点,该方法首先解组到空接口,然后确定它是切片还是单个字符串:

    package main
    
    import (
        "fmt"
        "encoding/json"
        "errors"
    )
    
    type container struct {
        Field customSlice
    }
    
    type customSlice []string
    
    func (c *customSlice) UnmarshalJSON(data []byte) error {
        var tmp interface{}
        err := json.Unmarshal(data, &tmp)
        if err != nil {
            return err
        }
        slice, ok := tmp.([]interface{})
        if ok {
            for _, item := range slice {
                *c = append(*c, item.(string))
            }
            return nil
        }
        theString, ok := tmp.(string)
        if ok {
            *c = append(*c, theString)
            return nil
        }
        return errors.New("Field neither slice or string")
    }
    
    func main() {
        jsonInputSlice := `{"Field":["a"]}`
        jsonInputString := `{"Field":"a"}`
        var containerSlice container
        var containerString container
        err := json.Unmarshal([]byte(jsonInputSlice), &containerSlice)
        if err != nil {
            panic(err)
        }
        fmt.Println(containerSlice)
        err = json.Unmarshal([]byte(jsonInputString), &containerString)
        if err != nil {
            panic(err)
        }
        fmt.Println(containerString)
    
    }
    

    https://play.golang.org/p/mAhJBNhE1yc

        2
  •  1
  •   Nihanth Dara    7 年前

    您可以通过多种方式实现这一点。其中一种方法是定义 Resource interface{} 然后再进行解析。游乐场- https://play.golang.org/p/PiLaa0DySEj

    package main
    
    import (
        "encoding/json"
        "fmt"
        "reflect"
    )
    
    type PolicyDocument struct {
        Version   string
        Statement []StatementEntry
    }
    
    type StatementEntry struct {
        Effect   string
        Action   []string
        Resource interface{}
    }
    
    func main() {
    
        data := `{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "ssm:PutParameter",
                    "ssm:DeleteParameter",
                    "ssm:DescribeInstancePatchStates",
                    "elasticloadbalancing:RegisterTargets",
                    "elasticloadbalancing:DescribeTargetHealth",
                    "elasticloadbalancing:DescribeTargetGroups",
                    "elasticloadbalancing:DeregisterTargets",
                    "ssm:GetParameter"
                ],
                "Resource": "*"
            }
        ]
    }`
    
        convertPolicy(data)
    
        data = `{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "s3:ListBucket"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::SageMaker"
                ]
            },
            {
                "Action": [
                    "s3:GetObject",
                    "s3:PutObject",
                    "s3:DeleteObject"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::SageMaker/*"
                ]
            }
        ]
    }`
    
        convertPolicy(data)
    
    }
    
    func convertPolicy(data string) {
        var doc PolicyDocument
        err1 := json.Unmarshal([]byte(data), &doc)
    
        if err1 != nil {
            fmt.Println(err1)
        }
    
        //find out the type of resource string or []string
        for _, statement := range doc.Statement {
            fmt.Println("statement.Resource was of type - ", reflect.TypeOf(statement.Resource))
            if reflect.TypeOf(statement.Resource).Name() != "string" {
                // we will convert the []interface to []string
                x := statement.Resource.([]interface{})
                y := make([]string, len(x))
                for i := 0; i < len(x); i++ {
                    y[i] = x[i].(string)
                }
                statement.Resource = y
                fmt.Println("statement.Resource is converted to type - ", reflect.TypeOf(statement.Resource))
            }
        }
    
        fmt.Printf("\n----\n%v\n---\n", doc)
    }