diff --git a/pkg/multicloud/aws/organizations.go b/pkg/multicloud/aws/organizations.go index 66dc61b79b..093b4b428b 100644 --- a/pkg/multicloud/aws/organizations.go +++ b/pkg/multicloud/aws/organizations.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/organizations" + "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" @@ -30,6 +31,127 @@ type SAccount struct { IsMaster bool `json:"is_master"` } +/* + * { + * Arn: "arn:aws:organizations::031871565791:policy/o-gn75phg8ge/service_control_policy/p-4l9recev", + * AwsManaged: false, + * Description: "Create Preventive SCP Guardrails", + * Id: "p-4l9recev", + * Name: "SCP-PREVENTIVE-GUARDRAILS", + * Type: "SERVICE_CONTROL_POLICY" + * } + */ +type SOrgPolicy struct { + Arn string `json:"arn"` + AwsManaged bool `json:"aws_managed"` + Description string `json:"description"` + Id string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` +} + +const ( + SERVICE_CONTROL_POLICY = "SERVICE_CONTROL_POLICY" + TAG_POLICY = "TAG_POLICY" + BACKUP_POLICY = "BACKUP_POLICY" + AISERVICES_OPT_OUT_POLICY = "AISERVICES_OPT_OUT_POLICY" +) + +func (r *SRegion) ListPolicies(filter string) ([]SOrgPolicy, error) { + orgCli, err := r.getOrganizationClient() + if err != nil { + return nil, errors.Wrap(err, "GetOrganizationClient") + } + var nextToken *string + policies := make([]SOrgPolicy, 0) + + for { + input := organizations.ListPoliciesInput{} + input.SetFilter(filter) + if nextToken != nil { + input.SetNextToken(*nextToken) + } + parts, err := orgCli.ListPolicies(&input) + if err != nil { + return nil, errors.Wrap(err, "ListPolicies") + } + for _, pPtr := range parts.Policies { + p := SOrgPolicy{ + Arn: *pPtr.Arn, + AwsManaged: *pPtr.AwsManaged, + Description: *pPtr.Description, + Id: *pPtr.Id, + Name: *pPtr.Name, + Type: *pPtr.Type, + } + policies = append(policies, p) + } + if parts.NextToken == nil || len(*parts.NextToken) == 0 { + break + } else { + nextToken = parts.NextToken + } + } + return policies, nil +} + +func (r *SRegion) ListPoliciesForTarget(filter string, targetId string) ([]SOrgPolicy, error) { + orgCli, err := r.getOrganizationClient() + if err != nil { + return nil, errors.Wrap(err, "GetOrganizationClient") + } + var nextToken *string + policies := make([]SOrgPolicy, 0) + + for { + input := organizations.ListPoliciesForTargetInput{} + input.SetFilter(filter) + input.SetTargetId(targetId) + if nextToken != nil { + input.SetNextToken(*nextToken) + } + parts, err := orgCli.ListPoliciesForTarget(&input) + if err != nil { + return nil, errors.Wrap(err, "ListPoliciesForTarget") + } + for _, pPtr := range parts.Policies { + p := SOrgPolicy{ + Arn: *pPtr.Arn, + AwsManaged: *pPtr.AwsManaged, + Description: *pPtr.Description, + Id: *pPtr.Id, + Name: *pPtr.Name, + Type: *pPtr.Type, + } + policies = append(policies, p) + } + if parts.NextToken == nil || len(*parts.NextToken) == 0 { + break + } else { + nextToken = parts.NextToken + } + } + return policies, nil +} + +func (r *SRegion) DescribeOrgPolicy(pId string) (jsonutils.JSONObject, error) { + orgCli, err := r.getOrganizationClient() + if err != nil { + return nil, errors.Wrap(err, "GetOrganizationClient") + } + input := organizations.DescribePolicyInput{} + input.SetPolicyId(pId) + output, err := orgCli.DescribePolicy(&input) + if err != nil { + return nil, errors.Wrap(err, "DescribePolicy") + } + content, err := jsonutils.ParseString(*output.Policy.Content) + if err != nil { + return nil, errors.Wrap(err, "ParseJSON") + } + return content, nil +} + func (r *SRegion) ListAccounts() ([]SAccount, error) { orgCli, err := r.getOrganizationClient() if err != nil { @@ -128,3 +250,33 @@ func (self *SAwsClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) { return subAccounts, nil } } + +func (r *SRegion) ListParents(childId string) error { + orgCli, err := r.getOrganizationClient() + if err != nil { + return errors.Wrap(err, "GetOrganizationClient") + } + input := organizations.ListParentsInput{} + input.SetChildId(childId) + parents, err := orgCli.ListParents(&input) + if err != nil { + return errors.Wrap(err, "ListParents") + } + log.Debugf("%#v", parents) + return nil +} + +func (r *SRegion) DescribeOrganizationalUnit(ouId string) error { + orgCli, err := r.getOrganizationClient() + if err != nil { + return errors.Wrap(err, "GetOrganizationClient") + } + input := organizations.DescribeOrganizationalUnitInput{} + input.SetOrganizationalUnitId(ouId) + output, err := orgCli.DescribeOrganizationalUnit(&input) + if err != nil { + return errors.Wrap(err, "DescribeOrganizationUnit") + } + log.Debugf("%#v", output) + return nil +} diff --git a/pkg/multicloud/aws/shell/organizations.go b/pkg/multicloud/aws/shell/organizations.go index c500a8e8fa..3e6ead5714 100644 --- a/pkg/multicloud/aws/shell/organizations.go +++ b/pkg/multicloud/aws/shell/organizations.go @@ -15,6 +15,8 @@ package shell import ( + "fmt" + "yunion.io/x/onecloud/pkg/multicloud/aws" "yunion.io/x/onecloud/pkg/util/shellutils" ) @@ -30,4 +32,63 @@ func init() { printList(accounts, 0, 0, 0, []string{}) return nil }) + + type OrganizationPoliciesListOptions struct { + FILTER string `json:"filter" choices:"SERVICE_CONTROL_POLICY|TAG_POLICY|BACKUP_POLICY|AISERVICES_OPT_OUT_POLICY"` + } + shellutils.R(&OrganizationPoliciesListOptions{}, "org-policy-list", "List policies of organizations", func(cli *aws.SRegion, args *OrganizationPoliciesListOptions) error { + policies, err := cli.ListPolicies(args.FILTER) + if err != nil { + return err + } + printList(policies, 0, 0, 0, []string{}) + return nil + }) + + type OrganizationPolicyShowOptions struct { + ID string `json:"id"` + } + shellutils.R(&OrganizationPolicyShowOptions{}, "org-policy-show", "Show details of an organizations policy", func(cli *aws.SRegion, args *OrganizationPolicyShowOptions) error { + content, err := cli.DescribeOrgPolicy(args.ID) + if err != nil { + return err + } + fmt.Println(content.PrettyString()) + return nil + }) + + type OrganizationPoliciesListForTargetOptions struct { + OrganizationPoliciesListOptions + TARGET string `json:"target"` + } + shellutils.R(&OrganizationPoliciesListForTargetOptions{}, "org-target-policy-list", "List policies for target of organizations", func(cli *aws.SRegion, args *OrganizationPoliciesListForTargetOptions) error { + policies, err := cli.ListPoliciesForTarget(args.FILTER, args.TARGET) + if err != nil { + return err + } + printList(policies, 0, 0, 0, []string{}) + return nil + }) + + type OrganizationParentsListOptions struct { + ID string `json:"id"` + } + shellutils.R(&OrganizationParentsListOptions{}, "org-parent-list", "List parent nodes of a child node", func(cli *aws.SRegion, args *OrganizationParentsListOptions) error { + err := cli.ListParents(args.ID) + if err != nil { + return err + } + return nil + }) + + type OrganizationalUnitShowOptions struct { + ID string `help:"Id of organizational unit"` + } + shellutils.R(&OrganizationalUnitShowOptions{}, "org-ou-show", "Show details of organizational unit", func(cli *aws.SRegion, args *OrganizationalUnitShowOptions) error { + err := cli.DescribeOrganizationalUnit(args.ID) + if err != nil { + return err + } + return nil + }) }