mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-29 03:51:54 +08:00
feature: saml for cloudid
This commit is contained in:
@@ -17,22 +17,22 @@ package cloudid
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudgroups).WithKeyword("cloud-group")
|
||||
cmd.List(&options.CloudgroupListOptions{})
|
||||
cmd.Create(&options.CloudgroupCreateOptions{})
|
||||
cmd.Show(&options.CloudgroupIdOptions{})
|
||||
cmd.Delete(&options.CloudgroupIdOptions{})
|
||||
cmd.Perform("syncstatus", &options.CloudgroupIdOptions{})
|
||||
cmd.Perform("attach-policy", &options.CloudgroupPolicyOptions{})
|
||||
cmd.Perform("detach-policy", &options.CloudgroupPolicyOptions{})
|
||||
cmd.Perform("add-user", &options.CloudgroupUserOptions{})
|
||||
cmd.Perform("remove-user", &options.CloudgroupUserOptions{})
|
||||
cmd.Perform("set-policies", &options.CloudgroupPolicyOptions{})
|
||||
cmd.Perform("set-users", &options.CloudgroupUserOptions{})
|
||||
cmd.Perform("public", &options.CloudgroupPublicOptions{})
|
||||
cmd.Perform("private", &options.CloudgroupIdOptions{})
|
||||
cmd.List(&cloudid.CloudgroupListOptions{})
|
||||
cmd.Create(&cloudid.CloudgroupCreateOptions{})
|
||||
cmd.Show(&cloudid.CloudgroupIdOptions{})
|
||||
cmd.Delete(&cloudid.CloudgroupIdOptions{})
|
||||
cmd.Perform("syncstatus", &cloudid.CloudgroupIdOptions{})
|
||||
cmd.Perform("attach-policy", &cloudid.CloudgroupPolicyOptions{})
|
||||
cmd.Perform("detach-policy", &cloudid.CloudgroupPolicyOptions{})
|
||||
cmd.Perform("add-user", &cloudid.CloudgroupUserOptions{})
|
||||
cmd.Perform("remove-user", &cloudid.CloudgroupUserOptions{})
|
||||
cmd.Perform("set-policies", &cloudid.CloudgroupPolicyOptions{})
|
||||
cmd.Perform("set-users", &cloudid.CloudgroupUserOptions{})
|
||||
cmd.Perform("public", &cloudid.CloudgroupPublicOptions{})
|
||||
cmd.Perform("private", &cloudid.CloudgroupIdOptions{})
|
||||
}
|
||||
|
||||
@@ -15,59 +15,15 @@
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type CloudgroupcacheListOptions struct {
|
||||
options.BaseListOptions
|
||||
|
||||
CloudgroupId string `json:"cloudgroup_id"`
|
||||
}
|
||||
R(&CloudgroupcacheListOptions{}, "cloud-group-cache-list", "List cloud group caches", func(s *mcclient.ClientSession, opts *CloudgroupcacheListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Cloudgroupcaches.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.Cloudgroupcaches.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type CloudgroupcacheIdOption struct {
|
||||
ID string `help:"Cloudgroup Id"`
|
||||
}
|
||||
|
||||
R(&CloudgroupcacheIdOption{}, "cloud-group-cache-show", "Show cloud groupcache details", func(s *mcclient.ClientSession, opts *CloudgroupcacheIdOption) error {
|
||||
result, err := modules.Cloudgroupcaches.Get(s, opts.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&CloudgroupcacheIdOption{}, "cloud-group-cache-syncstatus", "Sync cloudgroupcache", func(s *mcclient.ClientSession, opts *CloudgroupcacheIdOption) error {
|
||||
result, err := modules.Cloudgroupcaches.PerformAction(s, opts.ID, "syncstatus", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&CloudgroupcacheIdOption{}, "cloud-group-cache-delete", "Delete cloudgroupcache", func(s *mcclient.ClientSession, opts *CloudgroupcacheIdOption) error {
|
||||
result, err := modules.Cloudgroupcaches.Delete(s, opts.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudgroupcaches).WithKeyword("cloud-group-cache")
|
||||
cmd.List(&cloudid.CloudgroupcacheListOptions{})
|
||||
cmd.Show(&cloudid.CloudgroupcacheIdOption{})
|
||||
cmd.Delete(&cloudid.CloudgroupcacheIdOption{})
|
||||
cmd.Perform("syncstatus", &cloudid.CloudgroupcacheIdOption{})
|
||||
}
|
||||
|
||||
@@ -15,58 +15,12 @@
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type CloudgroupPolicyListOptions struct {
|
||||
options.BaseListOptions
|
||||
Cloudgroup string `help:"ID or Name of Cloudgroup"`
|
||||
Cloudpolicy string `help:"Policy ID or name"`
|
||||
}
|
||||
R(&CloudgroupPolicyListOptions{}, "cloud-group-policy-list", "List cloudgroup cloudpolicy pairs", func(s *mcclient.ClientSession, args *CloudgroupPolicyListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = args.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
var result *modulebase.ListResult
|
||||
var err error
|
||||
if len(args.Cloudgroup) > 0 {
|
||||
result, err = modules.Cloudgrouppolicies.ListDescendent(s, args.Cloudgroup, params)
|
||||
} else if len(args.Cloudpolicy) > 0 {
|
||||
result, err = modules.Cloudgrouppolicies.ListDescendent2(s, args.Cloudpolicy, params)
|
||||
} else {
|
||||
result, err = modules.Cloudgrouppolicies.List(s, params)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.Cloudgrouppolicies.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type CloudgroupPolicyDetailOptions struct {
|
||||
CLOUDUSER string `help:"ID or Name of Cloudgroup"`
|
||||
CLOUDPOLICY string `help:"ID or Name of Cloudpolicy"`
|
||||
}
|
||||
R(&CloudgroupPolicyDetailOptions{}, "cloud-group-policy-show", "Show cloudgrouppolicy details", func(s *mcclient.ClientSession, args *CloudgroupPolicyDetailOptions) error {
|
||||
query := jsonutils.NewDict()
|
||||
result, err := modules.Cloudgrouppolicies.Get(s, args.CLOUDUSER, args.CLOUDPOLICY, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudgrouppolicies).WithKeyword("cloud-group-policy").WithContextManager(&modules.Cloudgroups)
|
||||
cmd.List(&cloudid.CloudgroupPolicyListOptions{})
|
||||
}
|
||||
|
||||
@@ -15,58 +15,12 @@
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type CloudgroupUserListOptions struct {
|
||||
options.BaseListOptions
|
||||
Cloudgroup string `help:"ID or Name of Cloudgroup"`
|
||||
Clouduser string `help:"User ID or name"`
|
||||
}
|
||||
R(&CloudgroupUserListOptions{}, "cloud-group-user-list", "List cloudgroup clouduser pairs", func(s *mcclient.ClientSession, args *CloudgroupUserListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = args.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
var result *modulebase.ListResult
|
||||
var err error
|
||||
if len(args.Cloudgroup) > 0 {
|
||||
result, err = modules.Cloudgroupusers.ListDescendent(s, args.Cloudgroup, params)
|
||||
} else if len(args.Clouduser) > 0 {
|
||||
result, err = modules.Cloudgroupusers.ListDescendent2(s, args.Clouduser, params)
|
||||
} else {
|
||||
result, err = modules.Cloudgroupusers.List(s, params)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.Cloudgroupusers.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type CloudgroupUserDetailOptions struct {
|
||||
CLOUDUSER string `help:"ID or Name of Cloudgroup"`
|
||||
CLOUDPOLICY string `help:"ID or Name of Clouduser"`
|
||||
}
|
||||
R(&CloudgroupUserDetailOptions{}, "cloud-group-user-show", "Show cloudgroupuser details", func(s *mcclient.ClientSession, args *CloudgroupUserDetailOptions) error {
|
||||
query := jsonutils.NewDict()
|
||||
result, err := modules.Cloudgroupusers.Get(s, args.CLOUDUSER, args.CLOUDPOLICY, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudgroupusers).WithKeyword("cloud-group-user").WithContextManager(&modules.Cloudusers)
|
||||
cmd.List(&cloudid.CloudgroupUserListOptions{})
|
||||
}
|
||||
|
||||
@@ -17,18 +17,18 @@ package cloudid
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudpolicies).WithKeyword("cloud-policy")
|
||||
cmd.Create(&options.CloudpolicyListOptions{})
|
||||
cmd.List(&options.CloudpolicyListOptions{})
|
||||
cmd.Show(&options.CloudpolicyIdOptions{})
|
||||
cmd.Update(&options.CloudpolicyUpdateOption{})
|
||||
cmd.Perform("syncstauts", &options.CloudpolicyIdOptions{})
|
||||
cmd.Perform("lock", &options.CloudpolicyIdOptions{})
|
||||
cmd.Perform("unlock", &options.CloudpolicyIdOptions{})
|
||||
cmd.Perform("assign-group", &options.CloudpolicyGroupOptions{})
|
||||
cmd.Perform("revoke-group", &options.CloudpolicyGroupOptions{})
|
||||
cmd.Create(&cloudid.CloudpolicyListOptions{})
|
||||
cmd.List(&cloudid.CloudpolicyListOptions{})
|
||||
cmd.Show(&cloudid.CloudpolicyIdOptions{})
|
||||
cmd.Update(&cloudid.CloudpolicyUpdateOption{})
|
||||
cmd.Perform("syncstauts", &cloudid.CloudpolicyIdOptions{})
|
||||
cmd.Perform("lock", &cloudid.CloudpolicyIdOptions{})
|
||||
cmd.Perform("unlock", &cloudid.CloudpolicyIdOptions{})
|
||||
cmd.Perform("assign-group", &cloudid.CloudpolicyGroupOptions{})
|
||||
cmd.Perform("revoke-group", &cloudid.CloudpolicyGroupOptions{})
|
||||
}
|
||||
|
||||
@@ -15,28 +15,12 @@
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type CloudpolicycacheListOptions struct {
|
||||
options.BaseListOptions
|
||||
|
||||
CloudpolyId string
|
||||
CloudaccountId string
|
||||
}
|
||||
R(&CloudpolicycacheListOptions{}, "cloud-policy-cache-list", "List cloud policy caches", func(s *mcclient.ClientSession, opts *CloudpolicycacheListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Cloudpolicycaches.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.Cloudpolicycaches.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudpolicycaches).WithKeyword("cloud-policy-cache")
|
||||
cmd.List(&cloudid.CloudpolicycacheListOptions{})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudroles).WithKeyword("cloud-role")
|
||||
cmd.List(&cloudid.CloudroleListOptions{})
|
||||
cmd.Delete(&cloudid.CloudroleIdOptions{})
|
||||
cmd.Show(&cloudid.CloudroleIdOptions{})
|
||||
cmd.Perform("purge", &cloudid.CloudroleIdOptions{})
|
||||
}
|
||||
@@ -15,58 +15,12 @@
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ClouduserPolicyListOptions struct {
|
||||
options.BaseListOptions
|
||||
Clouduser string `help:"ID or Name of Clouduser"`
|
||||
Cloudpolicy string `help:"Policy ID or name"`
|
||||
}
|
||||
R(&ClouduserPolicyListOptions{}, "cloud-user-policy-list", "List clouduser cloudpolicy pairs", func(s *mcclient.ClientSession, args *ClouduserPolicyListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = args.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
var result *modulebase.ListResult
|
||||
var err error
|
||||
if len(args.Clouduser) > 0 {
|
||||
result, err = modules.Clouduserpolicies.ListDescendent(s, args.Clouduser, params)
|
||||
} else if len(args.Cloudpolicy) > 0 {
|
||||
result, err = modules.Clouduserpolicies.ListDescendent2(s, args.Cloudpolicy, params)
|
||||
} else {
|
||||
result, err = modules.Clouduserpolicies.List(s, params)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.Clouduserpolicies.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type ClouduserPolicyDetailOptions struct {
|
||||
CLOUDUSER string `help:"ID or Name of Clouduser"`
|
||||
CLOUDPOLICY string `help:"ID or Name of Cloudpolicy"`
|
||||
}
|
||||
R(&ClouduserPolicyDetailOptions{}, "cloud-user-policy-show", "Show clouduserpolicy details", func(s *mcclient.ClientSession, args *ClouduserPolicyDetailOptions) error {
|
||||
query := jsonutils.NewDict()
|
||||
result, err := modules.Clouduserpolicies.Get(s, args.CLOUDUSER, args.CLOUDPOLICY, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
cmd := shell.NewResourceCmd(&modules.Clouduserpolicies).WithKeyword("cloud-user-policy").WithContextManager(&modules.Cloudpolicies)
|
||||
cmd.List(&cloudid.ClouduserPolicyListOptions{})
|
||||
}
|
||||
|
||||
@@ -17,22 +17,22 @@ package cloudid
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.Cloudusers).WithKeyword("cloud-user")
|
||||
cmd.List(&options.ClouduserListOptions{})
|
||||
cmd.Create(&options.ClouduserCreateOptions{})
|
||||
cmd.Show(&options.ClouduserIdOption{})
|
||||
cmd.Custom(shell.CustomActionGet, "login-info", &options.ClouduserIdOption{})
|
||||
cmd.Delete(&options.ClouduserIdOption{})
|
||||
cmd.Perform("sync", &options.ClouduserSyncOptions{})
|
||||
cmd.Perform("syncstatus", &options.ClouduserIdOption{})
|
||||
cmd.Perform("attach-policy", &options.ClouduserPolicyOptions{})
|
||||
cmd.Perform("detach-policy", &options.ClouduserPolicyOptions{})
|
||||
cmd.Perform("change-owner", &options.ClouduserChangeOwnerOptions{})
|
||||
cmd.Perform("reset-password", &options.ClouduserResetPasswordOptions{})
|
||||
cmd.Perform("cloud-user-join-group", &options.ClouduserGroupOptions{})
|
||||
cmd.Perform("cloud-user-leave-group", &options.ClouduserGroupOptions{})
|
||||
cmd.List(&cloudid.ClouduserListOptions{})
|
||||
cmd.Create(&cloudid.ClouduserCreateOptions{})
|
||||
cmd.Show(&cloudid.ClouduserIdOption{})
|
||||
cmd.Custom(shell.CustomActionGet, "login-info", &cloudid.ClouduserIdOption{})
|
||||
cmd.Delete(&cloudid.ClouduserIdOption{})
|
||||
cmd.Perform("sync", &cloudid.ClouduserSyncOptions{})
|
||||
cmd.Perform("syncstatus", &cloudid.ClouduserIdOption{})
|
||||
cmd.Perform("attach-policy", &cloudid.ClouduserPolicyOptions{})
|
||||
cmd.Perform("detach-policy", &cloudid.ClouduserPolicyOptions{})
|
||||
cmd.Perform("change-owner", &cloudid.ClouduserChangeOwnerOptions{})
|
||||
cmd.Perform("reset-password", &cloudid.ClouduserResetPasswordOptions{})
|
||||
cmd.Perform("cloud-user-join-group", &cloudid.ClouduserGroupOptions{})
|
||||
cmd.Perform("cloud-user-leave-group", &cloudid.ClouduserGroupOptions{})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.SAMLProviders).WithKeyword("saml-provider")
|
||||
cmd.List(&cloudid.SAMLProviderListOptions{})
|
||||
cmd.Create(&cloudid.SAMLProviderCreateOptions{})
|
||||
cmd.Show(&cloudid.SAMLProviderIdOptions{})
|
||||
cmd.Delete(&cloudid.SAMLProviderIdOptions{})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.Samlusers).WithKeyword("saml-user")
|
||||
cmd.List(&cloudid.SamluserListOptions{})
|
||||
cmd.Create(&cloudid.SamluserCreateOptions{})
|
||||
cmd.Show(&cloudid.SamluserIdOptions{})
|
||||
cmd.Delete(&cloudid.SamluserIdOptions{})
|
||||
}
|
||||
@@ -42,8 +42,7 @@ func NewProxyHandlerWithService(prefix string, serviceName string) *InfluxdbProx
|
||||
}
|
||||
|
||||
func requestManipulator(ctx context.Context, r *http.Request) (*http.Request, error) {
|
||||
r.Header.Del("Cookie")
|
||||
token := AppContextToken(ctx)
|
||||
token, _, _ := fetchAuthInfo(ctx, r)
|
||||
if token != nil {
|
||||
r.Header.Set("X-Auth-Token", token.GetTokenString())
|
||||
}
|
||||
|
||||
@@ -162,3 +162,13 @@ type CloudgroupSyncInput struct {
|
||||
|
||||
type CloudgroupUpdateInput struct {
|
||||
}
|
||||
|
||||
type CloudgroupResourceListInput struct {
|
||||
// 根据权限组Id过滤资源
|
||||
CloudgroupId string `json:"cloudgroup_id"`
|
||||
}
|
||||
|
||||
type CloudgroupResourceDetails struct {
|
||||
// 公有云用户名称
|
||||
Cloudgroup string `json:"cloudgroup"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
CLOUD_ROLE_STATUS_CREATING = "creating" // 创建中
|
||||
CLOUD_ROLE_STATUS_AVAILABLE = "available" // 正常
|
||||
CLOUD_ROLE_STATUS_DELETING = "deleting" // 删除中
|
||||
CLOUD_ROLE_STATUS_DELETE_FAILED = "delete_failed" // 删除失败
|
||||
)
|
||||
|
||||
type CloudroleListInput struct {
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
|
||||
CloudaccountResourceListInput
|
||||
}
|
||||
|
||||
type CloudroleDetails struct {
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
CloudaccountResourceDetails
|
||||
|
||||
SCloudrole
|
||||
}
|
||||
|
||||
type CloudrolePurgeInput struct {
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
SAML_PROVIDER_STATUS_AVAILABLE = "available"
|
||||
SAML_PROVIDER_STATUS_NOT_MATCH = "not_match"
|
||||
SAML_PROVIDER_STATUS_DELETING = "deleting"
|
||||
SAML_PROVIDER_STATUS_DELETE_FAILED = "delete_failed"
|
||||
SAML_PROVIDER_STATUS_UNKNOWN = "unknown"
|
||||
SAML_PROVIDER_STATUS_CREATING = "creating"
|
||||
SAML_PROVIDER_STATUS_CREATE_FAILED = "create_failed"
|
||||
SAML_PROVIDER_STATUS_UNVALIABLE = "unavailable"
|
||||
)
|
||||
|
||||
type SAMLProviderListInput struct {
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
CloudaccountResourceListInput
|
||||
}
|
||||
|
||||
type SAMLProviderDetails struct {
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
CloudaccountResourceDetails
|
||||
|
||||
SSAMLProvider
|
||||
}
|
||||
|
||||
type SAMLProviderCreateInput struct {
|
||||
apis.StatusInfrasResourceBaseCreateInput
|
||||
|
||||
CloudaccountId string `json:"cloudaccount_id"`
|
||||
|
||||
// swagger:ignore
|
||||
EntityId string `json:"entity_id"`
|
||||
|
||||
// swagger:ignore
|
||||
MetadataDocument string `json:"metadata_document"`
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
SAML_USER_STATUS_AVAILABLE = "available"
|
||||
)
|
||||
|
||||
type SamluserCreateInput struct {
|
||||
apis.StatusDomainLevelUserResourceCreateInput
|
||||
|
||||
// 权限组和账号必须是同一平台
|
||||
CloudgroupId string `json:"cloudgroup_id"`
|
||||
|
||||
// 权限组和账号必须是同一平台
|
||||
CloudaccountId string `json:"cloudaccount_id"`
|
||||
}
|
||||
|
||||
type SamluserListInput struct {
|
||||
apis.StatusDomainLevelUserResourceListInput
|
||||
CloudgroupResourceListInput
|
||||
CloudaccountResourceListInput
|
||||
}
|
||||
|
||||
type SamluserDetails struct {
|
||||
apis.StatusDomainLevelUserResourceDetails
|
||||
CloudgroupResourceDetails
|
||||
CloudaccountResourceDetails
|
||||
|
||||
SSamluser
|
||||
}
|
||||
@@ -18,13 +18,20 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
// SAMLProviderResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SAMLProviderResourceBase.
|
||||
type SAMLProviderResourceBase struct {
|
||||
SAMLProviderId string `json:"saml_provider_id"`
|
||||
}
|
||||
|
||||
// SCloudaccount is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SCloudaccount.
|
||||
type SCloudaccount struct {
|
||||
apis.SStandaloneResourceBase
|
||||
apis.SDomainizedResourceBase
|
||||
AccountId string `json:"account_id"`
|
||||
Provider string `json:"provider"`
|
||||
Brand string `json:"brand"`
|
||||
IamLoginUrl string `json:"iam_login_url"`
|
||||
SAMLAuth *bool `json:"saml_auth,omitempty"`
|
||||
}
|
||||
|
||||
// SCloudaccountResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SCloudaccountResourceBase.
|
||||
@@ -52,6 +59,11 @@ type SCloudgroupPolicy struct {
|
||||
SCloudpolicyResourceBase
|
||||
}
|
||||
|
||||
// SCloudgroupResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SCloudgroupResourceBase.
|
||||
type SCloudgroupResourceBase struct {
|
||||
CloudgroupId string `json:"cloudgroup_id"`
|
||||
}
|
||||
|
||||
// SCloudgroupUser is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SCloudgroupUser.
|
||||
type SCloudgroupUser struct {
|
||||
SCloudgroupJointsBase
|
||||
@@ -121,6 +133,16 @@ type SCloudproviderResourceBase struct {
|
||||
CloudproviderId string `json:"cloudprovider_id"`
|
||||
}
|
||||
|
||||
// SCloudrole is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SCloudrole.
|
||||
type SCloudrole struct {
|
||||
apis.SEnabledStatusInfrasResourceBase
|
||||
apis.SExternalizedResourceBase
|
||||
SCloudaccountResourceBase
|
||||
SAMLProviderResourceBase
|
||||
Document interface{} `json:"document"`
|
||||
OwnerId string `json:"owner_id"`
|
||||
}
|
||||
|
||||
// SClouduser is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SClouduser.
|
||||
type SClouduser struct {
|
||||
apis.SStatusDomainLevelUserResourceBase
|
||||
@@ -152,3 +174,20 @@ type SClouduserPolicy struct {
|
||||
type SClouduserResourceBase struct {
|
||||
ClouduserId string `json:"clouduser_id"`
|
||||
}
|
||||
|
||||
// SSAMLProvider is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SSAMLProvider.
|
||||
type SSAMLProvider struct {
|
||||
apis.SStatusInfrasResourceBase
|
||||
apis.SExternalizedResourceBase
|
||||
SCloudaccountResourceBase
|
||||
EntityId string `json:"entity_id"`
|
||||
MetadataDocument string `json:"metadata_document"`
|
||||
AuthUrl string `json:"auth_url"`
|
||||
}
|
||||
|
||||
// SSamluser is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudid/models.SSamluser.
|
||||
type SSamluser struct {
|
||||
apis.SStatusDomainLevelUserResourceBase
|
||||
SCloudgroupResourceBase
|
||||
SCloudaccountResourceBase
|
||||
}
|
||||
|
||||
@@ -191,6 +191,10 @@ type CloudaccountCreateInput struct {
|
||||
|
||||
cloudprovider.SCloudaccount
|
||||
cloudprovider.SCloudaccountCredential
|
||||
|
||||
// 是否启用SAML认证
|
||||
// default: false
|
||||
SAMLAuth *bool `json:"saml_auth"`
|
||||
}
|
||||
|
||||
type CloudaccountShareModeInput struct {
|
||||
@@ -404,13 +408,13 @@ type EnrollmentAccountQuery struct {
|
||||
|
||||
type GetCloudaccountSamlOutput struct {
|
||||
// cloudaccount SAML ServiceProvider entity ID
|
||||
EntityId string `json:"entity_id"`
|
||||
EntityId string `json:"entity_id,allowempty"`
|
||||
// redirect login URL for this cloudaccount
|
||||
RedirectLoginUrl string `json:"redirect_login_url"`
|
||||
RedirectLoginUrl string `json:"redirect_login_url,allowempty"`
|
||||
// redirect logout URL for this cloudaccount
|
||||
RedirectLogoutUrl string `json:"redirect_logout_url"`
|
||||
RedirectLogoutUrl string `json:"redirect_logout_url,allowempty"`
|
||||
// metadata URL for this cloudaccount
|
||||
MetadataUrl string `json:"metadata_url"`
|
||||
MetadataUrl string `json:"metadata_url,allowempty"`
|
||||
// initial SAML SSO login URL for this cloudaccount
|
||||
InitLoginUrl string `json:"init_login_url"`
|
||||
InitLoginUrl string `json:"init_login_url,allowempty"`
|
||||
}
|
||||
|
||||
@@ -202,6 +202,7 @@ type SCloudaccount struct {
|
||||
ProxySettingId string `json:"proxy_setting_id"`
|
||||
// 公有云子账号登录地址
|
||||
IamLoginUrl string `json:"iam_login_url"`
|
||||
SAMLAuth *bool `json:"saml_auth,omitempty"`
|
||||
}
|
||||
|
||||
// SCloudprovider is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCloudprovider.
|
||||
@@ -257,6 +258,11 @@ type SCloudproviderQuota struct {
|
||||
QuotaType string `json:"quota_type"`
|
||||
}
|
||||
|
||||
// SCloudproviderResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCloudproviderResourceBase.
|
||||
type SCloudproviderResourceBase struct {
|
||||
CloudproviderId string `json:"cloudprovider_id"`
|
||||
}
|
||||
|
||||
// SCloudproviderregion is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCloudproviderregion.
|
||||
type SCloudproviderregion struct {
|
||||
apis.SJointResourceBase
|
||||
@@ -271,6 +277,12 @@ type SCloudproviderregion struct {
|
||||
LastAutoSyncAt time.Time `json:"last_auto_sync_at"`
|
||||
}
|
||||
|
||||
// SCloudproviderschedtag is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCloudproviderschedtag.
|
||||
type SCloudproviderschedtag struct {
|
||||
SSchedtagJointsBase
|
||||
SCloudproviderResourceBase
|
||||
}
|
||||
|
||||
// SCloudregion is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCloudregion.
|
||||
type SCloudregion struct {
|
||||
apis.SEnabledStatusStandaloneResourceBase
|
||||
@@ -291,6 +303,12 @@ type SCloudregionResourceBase struct {
|
||||
CloudregionId string `json:"cloudregion_id"`
|
||||
}
|
||||
|
||||
// SCloudregionschedtag is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCloudregionschedtag.
|
||||
type SCloudregionschedtag struct {
|
||||
SSchedtagJointsBase
|
||||
SCloudregionResourceBase
|
||||
}
|
||||
|
||||
// SDBInstance is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SDBInstance.
|
||||
type SDBInstance struct {
|
||||
apis.SVirtualResourceBase
|
||||
@@ -499,6 +517,8 @@ type SDisk struct {
|
||||
// swap: 交换盘
|
||||
// example: sys
|
||||
DiskType string `json:"disk_type"`
|
||||
// cpu架构
|
||||
OsArch string `json:"os_arch"`
|
||||
// # is persistent
|
||||
Nonpersistent bool `json:"nonpersistent"`
|
||||
// 是否标记为SSD磁盘
|
||||
@@ -900,6 +920,9 @@ type SGuest struct {
|
||||
// 虚拟化技术
|
||||
// example: kvm
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
// 虚拟机CPU架构
|
||||
// example: x86 arm
|
||||
OsArch string `json:"os_arch"`
|
||||
// 套餐名称
|
||||
InstanceType string `json:"instance_type"`
|
||||
}
|
||||
@@ -1182,6 +1205,8 @@ type SHuaweiCachedLbbg struct {
|
||||
// SInstanceSnapshot is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SInstanceSnapshot.
|
||||
type SInstanceSnapshot struct {
|
||||
apis.SVirtualResourceBase
|
||||
apis.SExternalizedResourceBase
|
||||
SManagedResourceBase
|
||||
// 云主机Id
|
||||
GuestId string `json:"guest_id"`
|
||||
// 云主机配置
|
||||
@@ -1198,6 +1223,8 @@ type SInstanceSnapshot struct {
|
||||
KeypairId string `json:"keypair_id"`
|
||||
// 操作系统类型
|
||||
OsType string `json:"os_type"`
|
||||
// CPU架构
|
||||
OsArch string `json:"os_arch"`
|
||||
// 套餐名称
|
||||
InstanceType string `json:"instance_type"`
|
||||
}
|
||||
@@ -1253,6 +1280,7 @@ type SLoadbalancer struct {
|
||||
apis.SExternalizedResourceBase
|
||||
SManagedResourceBase
|
||||
SCloudregionResourceBase
|
||||
SDeletePreventableResourceBase
|
||||
// LB might optionally be in a VPC, vpc_id, manager_id, cloudregion_id
|
||||
SVpcResourceBase
|
||||
// zone_id
|
||||
@@ -1814,6 +1842,33 @@ type SRouteTable struct {
|
||||
Routes *SRoutes `json:"routes"`
|
||||
}
|
||||
|
||||
// SRouteTableAssociation is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SRouteTableAssociation.
|
||||
type SRouteTableAssociation struct {
|
||||
apis.SStatusStandaloneResourceBase
|
||||
apis.SExternalizedResourceBase
|
||||
SRouteTableResourceBase
|
||||
AssociationType string `json:"association_type"`
|
||||
AssociatedResourceId string `json:"associated_resource_id"`
|
||||
ExtAssociatedResourceId string `json:"ext_associated_resource_id"`
|
||||
}
|
||||
|
||||
// SRouteTableResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SRouteTableResourceBase.
|
||||
type SRouteTableResourceBase struct {
|
||||
RouteTableId string `json:"route_table_id"`
|
||||
}
|
||||
|
||||
// SRouteTableRouteSet is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SRouteTableRouteSet.
|
||||
type SRouteTableRouteSet struct {
|
||||
apis.SStatusStandaloneResourceBase
|
||||
apis.SExternalizedResourceBase
|
||||
SRouteTableResourceBase
|
||||
Type string `json:"type"`
|
||||
Cidr string `json:"cidr"`
|
||||
NextHopType string `json:"next_hop_type"`
|
||||
NextHopId string `json:"next_hop_id"`
|
||||
ExtNextHopId string `json:"ext_next_hop_id"`
|
||||
}
|
||||
|
||||
// SScalingActivity is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SScalingActivity.
|
||||
type SScalingActivity struct {
|
||||
apis.SStatusStandaloneResourceBase
|
||||
@@ -2085,6 +2140,7 @@ type SSnapshot struct {
|
||||
DiskType string `json:"disk_type"`
|
||||
// 操作系统类型
|
||||
OsType string `json:"os_type"`
|
||||
OsArch string `json:"os_arch"`
|
||||
// create disk from snapshot, snapshot as disk backing file
|
||||
RefCount int `json:"ref_count"`
|
||||
BackingDiskId string `json:"backing_disk_id"`
|
||||
@@ -2253,9 +2309,11 @@ type SVpcPeeringConnection struct {
|
||||
apis.SEnabledStatusInfrasResourceBase
|
||||
apis.SExternalizedResourceBase
|
||||
SVpcResourceBase
|
||||
PeerVpcId string `json:"peer_vpc_id"`
|
||||
PeerAccountId string `json:"peer_account_id"`
|
||||
Bandwidth int `json:"bandwidth"`
|
||||
ExtPeerVpcId string `json:"ext_peer_vpc_id"`
|
||||
ExtPeerAccountId string `json:"ext_peer_account_id"`
|
||||
PeerVpcId string `json:"peer_vpc_id"`
|
||||
PeerAccountId string `json:"peer_account_id"`
|
||||
Bandwidth int `json:"bandwidth"`
|
||||
}
|
||||
|
||||
// SVpcResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SVpcResourceBase.
|
||||
@@ -2300,3 +2358,9 @@ type SZone struct {
|
||||
type SZoneResourceBase struct {
|
||||
ZoneId string `json:"zone_id"`
|
||||
}
|
||||
|
||||
// SZoneschedtag is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SZoneschedtag.
|
||||
type SZoneschedtag struct {
|
||||
SSchedtagJointsBase
|
||||
SZoneResourceBase
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
type SGuestImage struct {
|
||||
apis.SSharableVirtualResourceBase
|
||||
Protected *bool `json:"protected,omitempty"`
|
||||
// 操作系统CPU架构
|
||||
OsArch string `json:"os_arch"`
|
||||
}
|
||||
|
||||
// SGuestImageJoint is an autogenerated struct via yunion.io/x/onecloud/pkg/image/models.SGuestImageJoint.
|
||||
@@ -57,6 +59,8 @@ type SImage struct {
|
||||
IsGuestImage *bool `json:"is_guest_image,omitempty"`
|
||||
// 是否是数据盘镜像
|
||||
IsData *bool `json:"is_data,omitempty"`
|
||||
// 操作系统CPU架构
|
||||
OsArch string `json:"os_arch"`
|
||||
// image copy from url, save origin checksum before probe
|
||||
// 从镜像时长导入的镜像校验和
|
||||
OssChecksum string `json:"oss_checksum"`
|
||||
|
||||
@@ -53,9 +53,14 @@ type SAlertDashBoard struct {
|
||||
apis.SEnabledResourceBase
|
||||
apis.SStatusStandaloneResourceBase
|
||||
apis.SScopedResourceBase
|
||||
Refresh string `json:"refresh"`
|
||||
Settings interface{} `json:"settings"`
|
||||
Message string `json:"message"`
|
||||
Refresh string `json:"refresh"`
|
||||
}
|
||||
|
||||
// SAlertDashboardPanel is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertDashboardPanel.
|
||||
type SAlertDashboardPanel struct {
|
||||
apis.SVirtualJointResourceBase
|
||||
DashboardId string `json:"dashboard_id"`
|
||||
PanelId string `json:"panel_id"`
|
||||
}
|
||||
|
||||
// SAlertJointsBase is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertJointsBase.
|
||||
@@ -64,6 +69,14 @@ type SAlertJointsBase struct {
|
||||
AlertId string `json:"alert_id"`
|
||||
}
|
||||
|
||||
// SAlertPanel is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertPanel.
|
||||
type SAlertPanel struct {
|
||||
apis.SStatusStandaloneResourceBase
|
||||
apis.SScopedResourceBase
|
||||
Settings interface{} `json:"settings"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// SAlertRecord is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertRecord.
|
||||
type SAlertRecord struct {
|
||||
// db.SVirtualResourceBase
|
||||
|
||||
@@ -17,8 +17,10 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/http/httpproxy"
|
||||
|
||||
@@ -67,9 +69,11 @@ type SCloudaccount struct {
|
||||
db.SStandaloneResourceBase
|
||||
db.SDomainizedResourceBase
|
||||
|
||||
Provider string `width:"64" charset:"ascii" list:"domain"`
|
||||
Brand string `width:"64" charset:"utf8" nullable:"true" list:"domain"`
|
||||
IamLoginUrl string `width:"512" charset:"ascii"`
|
||||
AccountId string `width:"128" charset:"utf8" nullable:"true" list:"domain" create:"domain_optional"`
|
||||
Provider string `width:"64" charset:"ascii" list:"domain"`
|
||||
Brand string `width:"64" charset:"utf8" nullable:"true" list:"domain"`
|
||||
IamLoginUrl string `width:"512" charset:"ascii"`
|
||||
SAMLAuth tristate.TriState `nullable:"false" list:"domain" default:"false"`
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) GetResourceCount() ([]db.SScopeResourceCount, error) {
|
||||
@@ -206,6 +210,34 @@ func (self *SCloudaccount) removeCloudgroupcaches(ctx context.Context, userCred
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) removeSAMLProviders(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
samls, err := self.GetSAMLProviders()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetSAMLProviders")
|
||||
}
|
||||
for i := range samls {
|
||||
err = samls[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "samls[i].RealDelete")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) removeCloudroles(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
roles, err := self.GetCloudroles()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetCloudroles")
|
||||
}
|
||||
for i := range roles {
|
||||
err = roles[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "roles.RealDelete")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) syncRemoveCloudaccount(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := self.syncRemoveClouduser(ctx, userCred)
|
||||
if err != nil {
|
||||
@@ -222,9 +254,48 @@ func (self *SCloudaccount) syncRemoveCloudaccount(ctx context.Context, userCred
|
||||
return errors.Wrap(err, "removeCloudgroupcaches")
|
||||
}
|
||||
|
||||
err = self.removeSAMLProviders(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "removeSAMLProviders")
|
||||
}
|
||||
|
||||
err = self.removeCloudroles(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "removeCloudroles")
|
||||
}
|
||||
|
||||
err = self.removeSamluser(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "syncRemoveSamluser")
|
||||
}
|
||||
|
||||
return self.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetSamlusers() ([]SSamluser, error) {
|
||||
q := SamluserManager.Query().Equals("cloudaccount_id", self.Id)
|
||||
users := []SSamluser{}
|
||||
err := db.FetchModelObjects(SamluserManager, q, &users)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) removeSamluser(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
users, err := self.GetSamlusers()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetSamusers")
|
||||
}
|
||||
for i := range users {
|
||||
err = users[i].Delete(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "delete %s(%s)", users[i].Name, users[i].Id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) syncRemoveClouduser(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
users, err := self.getCloudusers()
|
||||
if err != nil {
|
||||
@@ -248,6 +319,9 @@ func (manager *SCloudaccountManager) newFromICloudaccount(ctx context.Context, u
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Insert")
|
||||
}
|
||||
if account.SAMLAuth.IsTrue() {
|
||||
account.StartSAMLProviderCreateTask(ctx, userCred)
|
||||
}
|
||||
|
||||
return account, nil
|
||||
}
|
||||
@@ -258,11 +332,14 @@ func (self *SCloudaccount) syncWithICloudaccount(ctx context.Context, userCred m
|
||||
self.DomainId = account.DomainId
|
||||
self.Brand = account.Brand
|
||||
self.IamLoginUrl = account.IamLoginUrl
|
||||
self.SAMLAuth = account.SAMLAuth
|
||||
self.AccountId = account.AccountId
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "db.UpdateWithLock")
|
||||
}
|
||||
self.StartSAMLProviderCreateTask(ctx, userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -278,6 +355,16 @@ func (manager *SCloudaccountManager) SyncCloudaccounts(ctx context.Context, user
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) StartSyncSamlProvidersTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
params := jsonutils.NewDict()
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SyncSAMLProvidersTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self SCloudaccount) GetGlobalId() string {
|
||||
return self.Id
|
||||
}
|
||||
@@ -407,6 +494,8 @@ func (account *SCloudDelegate) GetProvider() (cloudprovider.ICloudProvider, erro
|
||||
Account: account.Account,
|
||||
Secret: passwd,
|
||||
ProxyFunc: proxyFunc,
|
||||
|
||||
AccountId: account.Id,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -463,14 +552,12 @@ func (self *SCloudaccount) SyncCloudusers(ctx context.Context, userCred mcclient
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i++ {
|
||||
if len(removed[i].ExternalId) > 0 {
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
|
||||
for i := 0; i < len(commondb); i++ {
|
||||
@@ -860,7 +947,7 @@ func (self *SCloudaccount) syncCloudprovider(ctx context.Context, userCred mccli
|
||||
for i := 0; i < len(removed); i++ {
|
||||
err = removed[i].Delete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
@@ -970,6 +1057,180 @@ func (manager *SCloudaccountManager) SyncCloudidResources(ctx context.Context, u
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) IsSAMLProviderValid() (*SSAMLProvider, bool) {
|
||||
provider, err := self.RegisterSAMProvider()
|
||||
if err != nil {
|
||||
return provider, false
|
||||
}
|
||||
if len(provider.ExternalId) == 0 {
|
||||
return provider, false
|
||||
}
|
||||
return provider, true
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) RegisterSAMProvider() (*SSAMLProvider, error) {
|
||||
if len(options.Options.ApiServer) == 0 {
|
||||
return nil, fmt.Errorf("empty api server")
|
||||
}
|
||||
sps, err := self.GetSAMLProviders()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProviders")
|
||||
}
|
||||
for i := range sps {
|
||||
if sps[i].EntityId == options.Options.ApiServer {
|
||||
return &sps[i], nil
|
||||
}
|
||||
}
|
||||
sp := &SSAMLProvider{}
|
||||
sp.SetModelManager(SAMLProviderManager, sp)
|
||||
sp.Name = func() string {
|
||||
name := strings.TrimPrefix(options.Options.ApiServer, "https://")
|
||||
name = strings.TrimPrefix(name, "http://")
|
||||
return name
|
||||
}()
|
||||
sp.EntityId = options.Options.ApiServer
|
||||
sp.CloudaccountId = self.Id
|
||||
sp.Status = api.SAML_PROVIDER_STATUS_CREATING
|
||||
metadata := SamlIdpInstance().GetMetadata(self.Id).String()
|
||||
sp.MetadataDocument = metadata
|
||||
err = SAMLProviderManager.TableSpec().Insert(context.TODO(), sp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Insert")
|
||||
}
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) StartSAMLProviderCreateTask(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if self.SAMLAuth.IsFalse() {
|
||||
return nil
|
||||
}
|
||||
sp, valid := self.IsSAMLProviderValid()
|
||||
if valid {
|
||||
return nil
|
||||
}
|
||||
return sp.StartSAMLProviderCreateTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) SyncSAMLProviders(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
accounts, err := manager.GetSupportCloudIdAccounts()
|
||||
if err != nil {
|
||||
log.Errorf("GetSupportCloudIdAccounts error: %v", err)
|
||||
return
|
||||
}
|
||||
for i := range accounts {
|
||||
err = accounts[i].StartSyncSamlProvidersTask(ctx, userCred, "")
|
||||
if err != nil {
|
||||
log.Errorf("StartSyncSamlProvidersTask for account %s(%s) error: %v", accounts[i].Name, accounts[i].Provider, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) SyncCloudroles(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
accounts, err := manager.GetSupportCloudIdAccounts()
|
||||
if err != nil {
|
||||
log.Errorf("GetSupportCloudIdAccounts error: %v", err)
|
||||
return
|
||||
}
|
||||
for i := range accounts {
|
||||
err = accounts[i].StartSyncCloudrolesTask(ctx, userCred, "")
|
||||
if err != nil {
|
||||
log.Errorf("StartSyncCloudrolesTask for account %s(%s) error: %v", accounts[i].Name, accounts[i].Provider, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) StartSyncCloudrolesTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
params := jsonutils.NewDict()
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SyncCloudrolesTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetSAMLProviders() ([]SSAMLProvider, error) {
|
||||
q := SAMLProviderManager.Query().Equals("cloudaccount_id", self.Id)
|
||||
samls := []SSAMLProvider{}
|
||||
err := db.FetchModelObjects(SAMLProviderManager, q, &samls)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return samls, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) SyncSAMLProviders(ctx context.Context, userCred mcclient.TokenCredential, samls []cloudprovider.ICloudSAMLProvider) compare.SyncResult {
|
||||
|
||||
result := compare.SyncResult{}
|
||||
|
||||
dbSamls, err := self.GetSAMLProviders()
|
||||
if err != nil {
|
||||
result.Error(errors.Wrap(err, "GetSAMLProviders"))
|
||||
return result
|
||||
}
|
||||
|
||||
removed := make([]SSAMLProvider, 0)
|
||||
commondb := make([]SSAMLProvider, 0)
|
||||
commonext := make([]cloudprovider.ICloudSAMLProvider, 0)
|
||||
added := make([]cloudprovider.ICloudSAMLProvider, 0)
|
||||
|
||||
err = compare.CompareSets(dbSamls, samls, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
result.Error(errors.Wrap(err, "compare.CompareSets"))
|
||||
return result
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i++ {
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
|
||||
for i := 0; i < len(commondb); i++ {
|
||||
err = commondb[i].SyncWithCloudSAMLProvider(ctx, userCred, commonext[i])
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
result.Update()
|
||||
}
|
||||
|
||||
for i := 0; i < len(added); i++ {
|
||||
err = self.newFromCloudSAMLProvider(ctx, userCred, added[i])
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
continue
|
||||
}
|
||||
result.Add()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) newFromCloudSAMLProvider(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudSAMLProvider) error {
|
||||
saml := &SSAMLProvider{}
|
||||
saml.SetModelManager(SAMLProviderManager, saml)
|
||||
saml.Name = ext.GetName()
|
||||
saml.ExternalId = ext.GetGlobalId()
|
||||
saml.DomainId = self.DomainId
|
||||
saml.CloudaccountId = self.Id
|
||||
metadata, err := ext.GetMetadataDocument()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get metadata from %s(%s) error: %v", self.Name, self.Provider, err)
|
||||
}
|
||||
saml.Status = ext.GetStatus()
|
||||
if metadata != nil {
|
||||
saml.EntityId = metadata.EntityId
|
||||
saml.MetadataDocument = metadata.String()
|
||||
}
|
||||
if saml.EntityId != options.Options.ApiServer {
|
||||
saml.Status = api.SAML_PROVIDER_STATUS_NOT_MATCH
|
||||
}
|
||||
return SAMLProviderManager.TableSpec().Insert(ctx, saml)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) StartSyncCloudIdResourcesTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
params := jsonutils.NewDict()
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SyncCloudIdResourcesTask", self, userCred, params, parentTaskId, "", nil)
|
||||
@@ -999,14 +1260,12 @@ func (self *SCloudaccount) SyncCloudgroupcaches(ctx context.Context, userCred mc
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i++ {
|
||||
if len(removed[i].ExternalId) > 0 { // 只删除云上已经删除过的组
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
|
||||
for i := 0; i < len(commondb); i++ {
|
||||
@@ -1335,3 +1594,174 @@ func (self *SCloudaccount) SyncSystemCloudpoliciesForCloud(ctx context.Context,
|
||||
log.Infof("Sync %s(%s) system policies for user %s result: %s", self.Name, self.Provider, clouduser.Name, result.Result())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetLocalUserCloudroles(userId, spId string) ([]SCloudrole, error) {
|
||||
roles := []SCloudrole{}
|
||||
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id).Equals("owner_id", userId).Equals("saml_provider_id", spId)
|
||||
err := db.FetchModelObjects(CloudroleManager, q, &roles)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) RegisterCloudrole(userId, spId string) (*SCloudrole, error) {
|
||||
roles, err := self.GetLocalUserCloudroles(userId, spId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetLocalUserCloudroles")
|
||||
}
|
||||
if len(roles) > 0 {
|
||||
return &roles[0], nil
|
||||
}
|
||||
user, err := db.UserCacheManager.FetchById(userId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "UserCacheManager.FetchById(%s)", userId)
|
||||
}
|
||||
role := &SCloudrole{}
|
||||
role.SetModelManager(CloudroleManager, role)
|
||||
role.CloudaccountId = self.Id
|
||||
role.OwnerId = userId
|
||||
role.SAMLProviderId = spId
|
||||
role.Name = user.GetName()
|
||||
role.Status = api.CLOUD_ROLE_STATUS_CREATING
|
||||
role.DomainId = self.DomainId
|
||||
return role, CloudroleManager.TableSpec().Insert(context.TODO(), role)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetCloudrole(userId string) (*SCloudrole, error) {
|
||||
sp, valid := self.IsSAMLProviderValid()
|
||||
if !valid {
|
||||
return nil, fmt.Errorf("SAMLProvider for account %s not ready", self.Id)
|
||||
}
|
||||
|
||||
return self.RegisterCloudrole(userId, sp.Id)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) SyncRole(userId string) (*SCloudrole, error) {
|
||||
role, err := self.GetCloudrole(userId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetCloudrole")
|
||||
}
|
||||
|
||||
err = role.SyncRoles()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SyncRoles")
|
||||
}
|
||||
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetCloudroles() ([]SCloudrole, error) {
|
||||
roles := []SCloudrole{}
|
||||
q := CloudroleManager.Query()
|
||||
err := db.FetchModelObjects(CloudroleManager, q, &roles)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) newCloudrole(ctx context.Context, userCred mcclient.TokenCredential, iRole cloudprovider.ICloudrole) error {
|
||||
role := &SCloudrole{}
|
||||
role.SetModelManager(CloudroleManager, role)
|
||||
role.Name = iRole.GetName()
|
||||
role.ExternalId = iRole.GetGlobalId()
|
||||
role.Document = iRole.GetDocument()
|
||||
if spId := iRole.GetSAMLProvider(); len(spId) > 0 {
|
||||
sp, _ := db.FetchByExternalIdAndManagerId(SAMLProviderManager, spId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
return q.Equals("cloudaccount_id", self.Id)
|
||||
})
|
||||
if sp != nil {
|
||||
role.SAMLProviderId = sp.GetId()
|
||||
}
|
||||
}
|
||||
role.CloudaccountId = self.Id
|
||||
role.Status = api.CLOUD_ROLE_STATUS_AVAILABLE
|
||||
return CloudroleManager.TableSpec().Insert(ctx, role)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) SyncCloudroles(ctx context.Context, userCred mcclient.TokenCredential, exts []cloudprovider.ICloudrole) compare.SyncResult {
|
||||
result := compare.SyncResult{}
|
||||
|
||||
roles, err := self.GetCloudroles()
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "GetCloudroles"))
|
||||
return result
|
||||
}
|
||||
|
||||
removed := make([]SCloudrole, 0)
|
||||
commondb := make([]SCloudrole, 0)
|
||||
commonext := make([]cloudprovider.ICloudrole, 0)
|
||||
added := make([]cloudprovider.ICloudrole, 0)
|
||||
|
||||
err = compare.CompareSets(roles, exts, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "compare.CompareSets"))
|
||||
return result
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i++ {
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
|
||||
for i := 0; i < len(commondb); i++ {
|
||||
err = commondb[i].syncWithCloudrole(ctx, userCred, commonext[i])
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
result.Update()
|
||||
}
|
||||
|
||||
for i := 0; i < len(added); i++ {
|
||||
err := self.newCloudrole(ctx, userCred, added[i])
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
continue
|
||||
}
|
||||
result.Add()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetUserCloudgroups(userId string) ([]string, error) {
|
||||
ret := []string{}
|
||||
q := CloudgroupManager.Query()
|
||||
samlusers := SamluserManager.Query("cloudgroup_id").Equals("owner_id", userId).Equals("cloudaccount_id", self.Id).SubQuery()
|
||||
q = q.In("id", samlusers)
|
||||
groups := []SCloudgroup{}
|
||||
err := db.FetchModelObjects(CloudgroupManager, q, &groups)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
if len(groups) == 0 {
|
||||
return ret, nil
|
||||
}
|
||||
for i := range groups {
|
||||
cache, err := CloudgroupcacheManager.Register(&groups[i], self)
|
||||
if err != nil {
|
||||
return []string{}, errors.Wrapf(err, "group cache Register")
|
||||
}
|
||||
if len(cache.ExternalId) > 0 {
|
||||
ret = append(ret, cache.Name)
|
||||
} else {
|
||||
s := auth.GetAdminSession(context.TODO(), options.Options.Region, "")
|
||||
_, err = cache.GetOrCreateICloudgroup(context.TODO(), s.GetToken())
|
||||
if err != nil {
|
||||
return []string{}, errors.Wrapf(err, "GetOrCreateICloudgroup")
|
||||
}
|
||||
cache, err := CloudgroupcacheManager.Register(&groups[i], self)
|
||||
if err != nil {
|
||||
return []string{}, errors.Wrapf(err, "group cache Register")
|
||||
}
|
||||
ret = append(ret, cache.Name)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -255,9 +255,37 @@ func (self *SCloudgroup) RealDelete(ctx context.Context, userCred mcclient.Token
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "remoteUsers")
|
||||
}
|
||||
err = self.removeSamlusers()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "removeSamlusers")
|
||||
}
|
||||
return self.SStatusInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SCloudgroup) GetSamlusers() ([]SSamluser, error) {
|
||||
q := SamluserManager.Query().Equals("cloudgroup_id", self.Id)
|
||||
users := []SSamluser{}
|
||||
err := db.FetchModelObjects(SamluserManager, q, &users)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (self *SCloudgroup) removeSamlusers() error {
|
||||
users, err := self.GetSamlusers()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetSamlusers")
|
||||
}
|
||||
for i := range users {
|
||||
err = users[i].Delete(context.TODO(), nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "rm saml user(%s)", users[i].Id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudgroup) removeUsers() error {
|
||||
users, err := self.GetCloudusers()
|
||||
if err != nil {
|
||||
|
||||
@@ -283,6 +283,7 @@ func (self *SCloudgroupcache) GetOrCreateICloudgroup(ctx context.Context, userCr
|
||||
return nil, errors.Wrap(err, "CreateICloudgroup")
|
||||
}
|
||||
_, err = db.Update(self, func() error {
|
||||
self.Name = groupName
|
||||
self.ExternalId = iGroup.GetGlobalId()
|
||||
self.Status = api.CLOUD_GROUP_CACHE_STATUS_AVAILABLE
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/reflectutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SCloudgroupResourceBaseManager struct {
|
||||
}
|
||||
|
||||
type SCloudgroupResourceBase struct {
|
||||
CloudgroupId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
func (self *SCloudgroupJointsBase) GetCloudgroup() (*SCloudgroup, error) {
|
||||
group, err := CloudgroupManager.FetchById(self.CloudgroupId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "FetchById")
|
||||
}
|
||||
return group.(*SCloudgroup), nil
|
||||
}
|
||||
|
||||
func (manager *SCloudgroupResourceBaseManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, groupCred mcclient.TokenCredential, query api.CloudgroupResourceListInput) (*sqlchemy.SQuery, error) {
|
||||
if len(query.CloudgroupId) > 0 {
|
||||
group, err := CloudgroupManager.FetchByIdOrName(nil, query.CloudgroupId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2("cloudgroup", query.CloudgroupId)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
q = q.Equals("cloudgroup_id", group.GetId())
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SCloudgroupResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
groupCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.CloudgroupResourceDetails {
|
||||
rows := make([]api.CloudgroupResourceDetails, len(objs))
|
||||
groupIds := make([]string, len(objs))
|
||||
for i := range objs {
|
||||
var base *SCloudgroupResourceBase
|
||||
err := reflectutils.FindAnonymouStructPointer(objs[i], &base)
|
||||
if err != nil {
|
||||
log.Errorf("Cannot find SCloudgroupResourceBase in %#v: %s", objs[i], err)
|
||||
} else if base != nil && len(base.CloudgroupId) > 0 {
|
||||
groupIds[i] = base.CloudgroupId
|
||||
}
|
||||
}
|
||||
groupMaps, err := db.FetchIdNameMap2(CloudgroupManager, groupIds)
|
||||
if err != nil {
|
||||
return rows
|
||||
}
|
||||
for i := range rows {
|
||||
rows[i].Cloudgroup, _ = groupMaps[groupIds[i]]
|
||||
}
|
||||
return rows
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/fatih/set.v0"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SCloudroleManager struct {
|
||||
db.SStatusInfrasResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SCloudaccountResourceBaseManager
|
||||
SAMLProviderResourceBaseManager
|
||||
}
|
||||
|
||||
var CloudroleManager *SCloudroleManager
|
||||
|
||||
func init() {
|
||||
CloudroleManager = &SCloudroleManager{
|
||||
SStatusInfrasResourceBaseManager: db.NewStatusInfrasResourceBaseManager(
|
||||
SCloudrole{},
|
||||
"cloudroles_tbl",
|
||||
"cloudrole",
|
||||
"cloudroles",
|
||||
),
|
||||
}
|
||||
CloudroleManager.SetVirtualObject(CloudroleManager)
|
||||
}
|
||||
|
||||
type SCloudrole struct {
|
||||
db.SEnabledStatusInfrasResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SCloudaccountResourceBase
|
||||
SAMLProviderResourceBase
|
||||
|
||||
Document *jsonutils.JSONDict `length:"long" charset:"ascii" list:"domain" update:"domain" create:"domain_required"`
|
||||
OwnerId string `width:"128" charset:"ascii" index:"true" list:"user" nullable:"false" create:"optional"`
|
||||
}
|
||||
|
||||
// 公有云角色列表
|
||||
func (manager *SCloudroleManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query api.CloudroleListInput) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
q, err = manager.SCloudaccountResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudaccountResourceListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
// 获取公有云角色详情
|
||||
func (self *SCloudrole) GetExtraDetails(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
isList bool,
|
||||
) (api.CloudroleDetails, error) {
|
||||
return api.CloudroleDetails{}, nil
|
||||
}
|
||||
|
||||
func (manager *SCloudroleManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.CloudroleDetails {
|
||||
rows := make([]api.CloudroleDetails, len(objs))
|
||||
infRows := manager.SStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
acRows := manager.SCloudaccountResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = api.CloudroleDetails{
|
||||
StatusInfrasResourceBaseDetails: infRows[i],
|
||||
CloudaccountResourceDetails: acRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
// 删除公有云角色
|
||||
func (self *SCloudrole) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return self.StartCloudroleDeleteTask(ctx, userCred, false, "")
|
||||
}
|
||||
|
||||
func (self *SCloudrole) StartCloudroleDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, purge bool, parentTaskId string) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewBool(purge), "purge")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "CloudroleDeleteTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
self.SetStatus(userCred, api.CLOUD_ROLE_STATUS_DELETING, "")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudrole) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowPerform(userCred, self, "purge")
|
||||
}
|
||||
|
||||
// 清除角色(不删除云上资源)
|
||||
func (self *SCloudrole) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudrolePurgeInput) (jsonutils.JSONObject, error) {
|
||||
return nil, self.StartCloudroleDeleteTask(ctx, userCred, true, "")
|
||||
}
|
||||
|
||||
func (self *SCloudrole) GetICloudrole() (cloudprovider.ICloudrole, error) {
|
||||
account, err := self.GetCloudaccount()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetCloudaccount")
|
||||
}
|
||||
provider, err := account.GetProvider()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetProvider")
|
||||
}
|
||||
if len(self.ExternalId) > 0 {
|
||||
iRole, err := provider.GetICloudroleById(self.ExternalId)
|
||||
if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, errors.Wrapf(err, "GetICloudroleById(%s)", self.ExternalId)
|
||||
}
|
||||
if err == nil {
|
||||
return iRole, nil
|
||||
}
|
||||
}
|
||||
sp, err := self.GetSAMLProvider()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProvider")
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
_, err := provider.GetICloudroleByName(self.Name)
|
||||
if err != nil && errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
break
|
||||
}
|
||||
info := strings.Split(self.Name, "-")
|
||||
num, err := strconv.Atoi(info[len(info)-1])
|
||||
if err != nil {
|
||||
info = append(info, "1")
|
||||
} else {
|
||||
info[len(info)-1] = fmt.Sprintf("%d", num+1)
|
||||
}
|
||||
self.Name = strings.Join(info, "-")
|
||||
}
|
||||
opts := &cloudprovider.SRoleCreateOptions{
|
||||
Name: self.Name,
|
||||
Desc: self.Description,
|
||||
SAMLProvider: sp.ExternalId,
|
||||
}
|
||||
iRole, err := provider.CreateICloudrole(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateICloudrole")
|
||||
}
|
||||
db.Update(self, func() error {
|
||||
self.ExternalId = iRole.GetGlobalId()
|
||||
self.Name = iRole.GetName()
|
||||
self.Document = iRole.GetDocument()
|
||||
self.Status = api.CLOUD_ROLE_STATUS_AVAILABLE
|
||||
return nil
|
||||
})
|
||||
return iRole, nil
|
||||
}
|
||||
|
||||
func (self *SCloudrole) GetCloudpolicies() ([]SCloudpolicy, error) {
|
||||
q := CloudpolicyManager.Query()
|
||||
samlUsers := SamluserManager.Query("cloudgroup_id").Equals("owner_id", self.OwnerId).Equals("cloudaccount_id", self.CloudaccountId).SubQuery()
|
||||
groups := CloudgroupManager.Query("id").In("id", samlUsers)
|
||||
gp := CloudgroupPolicyManager.Query("cloudpolicy_id").In("cloudgroup_id", groups).SubQuery()
|
||||
q = q.In("id", gp)
|
||||
policies := []SCloudpolicy{}
|
||||
err := db.FetchModelObjects(CloudpolicyManager, q, &policies)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func (self *SCloudrole) SyncRoles() error {
|
||||
iRole, err := self.GetICloudrole()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetICloudrole")
|
||||
}
|
||||
policies, err := self.GetCloudpolicies()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetICloudpolicies")
|
||||
}
|
||||
local := set.New(set.ThreadSafe)
|
||||
for i := range policies {
|
||||
if policies[i].PolicyType == api.CLOUD_POLICY_TYPE_SYSTEM {
|
||||
local.Add(policies[i].ExternalId)
|
||||
} else {
|
||||
}
|
||||
}
|
||||
iPolicies, err := iRole.GetICloudpolicies()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetICloudpolicies")
|
||||
}
|
||||
remote := set.New(set.ThreadSafe)
|
||||
for i := range iPolicies {
|
||||
remote.Add(iPolicies[i].GetGlobalId())
|
||||
}
|
||||
for _, id := range set.Difference(remote, local).List() {
|
||||
err = iRole.DetachPolicy(id.(string))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DetachPolicy(%s)", id)
|
||||
}
|
||||
}
|
||||
for _, id := range set.Difference(local, remote).List() {
|
||||
err = iRole.AttachPolicy(id.(string))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "AttachPolicy(%s)", id)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudrole) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return self.SStatusInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SCloudrole) syncWithCloudrole(ctx context.Context, userCred mcclient.TokenCredential, iRole cloudprovider.ICloudrole) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.Name = self.GetName()
|
||||
self.Document = iRole.GetDocument()
|
||||
self.Status = api.CLOUD_ROLE_STATUS_AVAILABLE
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SSAMLProviderManager struct {
|
||||
db.SStatusInfrasResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SCloudaccountResourceBaseManager
|
||||
}
|
||||
|
||||
var SAMLProviderManager *SSAMLProviderManager
|
||||
|
||||
func init() {
|
||||
SAMLProviderManager = &SSAMLProviderManager{
|
||||
SStatusInfrasResourceBaseManager: db.NewStatusInfrasResourceBaseManager(
|
||||
SSAMLProvider{},
|
||||
"saml_provider_tbl",
|
||||
"saml_provider",
|
||||
"saml_providers",
|
||||
),
|
||||
}
|
||||
SAMLProviderManager.SetVirtualObject(SAMLProviderManager)
|
||||
}
|
||||
|
||||
type SSAMLProvider struct {
|
||||
db.SStatusInfrasResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SCloudaccountResourceBase
|
||||
|
||||
EntityId string `get:"domain" create:"domain_optional" list:"domain"`
|
||||
MetadataDocument string `get:"domain" create:"domain_optional"`
|
||||
AuthUrl string `width:"512" charset:"ascii" get:"domain" list:"domain"`
|
||||
}
|
||||
|
||||
func (manager *SSAMLProviderManager) GetIVirtualModelManager() db.IVirtualModelManager {
|
||||
return manager.GetVirtualObject().(db.IVirtualModelManager)
|
||||
}
|
||||
|
||||
func (manager *SSAMLProviderManager) GetResourceCount() ([]db.SScopeResourceCount, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (manager *SSAMLProviderManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
|
||||
accountId, _ := data.GetString("cloudaccount_id")
|
||||
return jsonutils.Marshal(map[string]string{"cloudaccount_id": accountId})
|
||||
}
|
||||
|
||||
func (manager *SSAMLProviderManager) FilterByUniqValues(q *sqlchemy.SQuery, values jsonutils.JSONObject) *sqlchemy.SQuery {
|
||||
accountId, _ := values.GetString("cloudaccount_id")
|
||||
if len(accountId) > 0 {
|
||||
q = q.Equals("cloudaccount_id", accountId)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// 创建云账号的身份提供商
|
||||
func (manager *SSAMLProviderManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SAMLProviderCreateInput) (api.SAMLProviderCreateInput, error) {
|
||||
if len(input.CloudaccountId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("cloudaccount_id")
|
||||
}
|
||||
_, err := validators.ValidateModel(userCred, CloudaccountManager, &input.CloudaccountId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
input.EntityId = options.Options.ApiServer
|
||||
if len(input.EntityId) == 0 {
|
||||
return input, httperrors.NewResourceNotReadyError("not set api_server")
|
||||
}
|
||||
input.Name = strings.TrimPrefix(input.EntityId, "https://")
|
||||
input.Name = strings.TrimPrefix(input.Name, "http://")
|
||||
|
||||
input.MetadataDocument = SamlIdpInstance().GetMetadata(input.CloudaccountId).String()
|
||||
input.StatusInfrasResourceBaseCreateInput, err = manager.SStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.StartSAMLProviderCreateTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
// 公有云身份提供商列表
|
||||
func (manager *SSAMLProviderManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query api.SAMLProviderListInput) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q, err = manager.SCloudaccountResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudaccountResourceListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
// 删除
|
||||
func (self *SSAMLProvider) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
params := jsonutils.NewDict()
|
||||
return self.StartSAMLProviderDeleteTask(ctx, userCred, params, "")
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return self.SStatusInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) StartSAMLProviderDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SAMLProviderDeleteTask", self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
self.SetStatus(userCred, api.SAML_PROVIDER_STATUS_DELETING, "")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) StartSAMLProviderCreateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SAMLProviderCreateTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
self.SetStatus(userCred, api.SAML_PROVIDER_STATUS_CREATING, "")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) syncRemove(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return self.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) SyncWithCloudSAMLProvider(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudSAMLProvider) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.ExternalId = ext.GetGlobalId()
|
||||
self.AuthUrl = ext.GetAuthUrl()
|
||||
self.Status = ext.GetStatus()
|
||||
metadata, err := ext.GetMetadataDocument()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get metadata for %s error: %v", self.Name, err)
|
||||
}
|
||||
if metadata != nil {
|
||||
self.EntityId = metadata.EntityId
|
||||
self.MetadataDocument = metadata.String()
|
||||
}
|
||||
if self.EntityId != options.Options.ApiServer {
|
||||
self.Status = api.SAML_PROVIDER_STATUS_NOT_MATCH
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SSAMLProvider) GetMetadataDocument() (samlutils.EntityDescriptor, error) {
|
||||
return samlutils.ParseMetadata([]byte(self.MetadataDocument))
|
||||
}
|
||||
|
||||
func (manager *SSAMLProviderManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.SAMLProviderDetails {
|
||||
rows := make([]api.SAMLProviderDetails, len(objs))
|
||||
infRows := manager.SStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
acRows := manager.SCloudaccountResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = api.SAMLProviderDetails{
|
||||
StatusInfrasResourceBaseDetails: infRows[i],
|
||||
CloudaccountResourceDetails: acRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
)
|
||||
|
||||
type SamlInstance func() *idp.SSAMLIdpInstance
|
||||
|
||||
var (
|
||||
SamlIdpInstance SamlInstance = nil
|
||||
)
|
||||
|
||||
type ICloudSAMLLoginDriver interface {
|
||||
GetEntityID() string
|
||||
|
||||
GetMetadataFilename() string
|
||||
GetMetadataUrl() string
|
||||
|
||||
GetIdpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error)
|
||||
GetSpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccoutId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error)
|
||||
}
|
||||
|
||||
var (
|
||||
driverTable = make(map[string]ICloudSAMLLoginDriver)
|
||||
)
|
||||
|
||||
func Register(driver ICloudSAMLLoginDriver) {
|
||||
driverTable[driver.GetEntityID()] = driver
|
||||
}
|
||||
|
||||
func FindDriver(entityId string) ICloudSAMLLoginDriver {
|
||||
if driver, ok := driverTable[entityId]; ok {
|
||||
return driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func AllDrivers() map[string]ICloudSAMLLoginDriver {
|
||||
return driverTable
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import "yunion.io/x/pkg/errors"
|
||||
|
||||
type SAMLProviderResourceBaseManager struct {
|
||||
}
|
||||
|
||||
type SAMLProviderResourceBase struct {
|
||||
SAMLProviderId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" json:"saml_provider_id"`
|
||||
}
|
||||
|
||||
func (self *SAMLProviderResourceBase) GetSAMLProvider() (*SSAMLProvider, error) {
|
||||
sp, err := SAMLProviderManager.FetchById(self.SAMLProviderId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SAMLProviderManager.FetchById")
|
||||
}
|
||||
return sp.(*SSAMLProvider), nil
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SSamluserManager struct {
|
||||
db.SStatusDomainLevelUserResourceBaseManager
|
||||
SCloudgroupResourceBaseManager
|
||||
SCloudaccountResourceBaseManager
|
||||
}
|
||||
|
||||
var SamluserManager *SSamluserManager
|
||||
|
||||
func init() {
|
||||
SamluserManager = &SSamluserManager{
|
||||
SStatusDomainLevelUserResourceBaseManager: db.NewStatusDomainLevelUserResourceBaseManager(
|
||||
SSamluser{},
|
||||
"samlusers_tbl",
|
||||
"samluser",
|
||||
"samlusers",
|
||||
),
|
||||
}
|
||||
SamluserManager.SetVirtualObject(SamluserManager)
|
||||
}
|
||||
|
||||
type SSamluser struct {
|
||||
db.SStatusDomainLevelUserResourceBase
|
||||
SCloudgroupResourceBase
|
||||
SCloudaccountResourceBase
|
||||
}
|
||||
|
||||
func (manager *SSamluserManager) GetResourceCount() ([]db.SScopeResourceCount, error) {
|
||||
q := manager.Query()
|
||||
domainCnt, err := db.CalculateResourceCount(q, "domain_id")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CalculateResourceCount.domain_id")
|
||||
}
|
||||
q = manager.Query()
|
||||
userCnt, err := db.CalculateResourceCount(q, "owner_id")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CalculateResourceCount.owner_id")
|
||||
}
|
||||
return append(domainCnt, userCnt...), nil
|
||||
}
|
||||
|
||||
func (manager *SSamluserManager) GetIVirtualModelManager() db.IVirtualModelManager {
|
||||
return manager.GetVirtualObject().(db.IVirtualModelManager)
|
||||
}
|
||||
|
||||
func (manager *SSamluserManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
|
||||
groupId, _ := data.GetString("cloudgroup_id")
|
||||
accountId, _ := data.GetString("cloudaccount_id")
|
||||
return jsonutils.Marshal(map[string]string{"cloudgroup_id": groupId, "cloudaccount_id": accountId})
|
||||
}
|
||||
|
||||
func (manager *SSamluserManager) FilterByUniqValues(q *sqlchemy.SQuery, values jsonutils.JSONObject) *sqlchemy.SQuery {
|
||||
groupId, _ := values.GetString("cloudgroup_id")
|
||||
accountId, _ := values.GetString("cloudaccount_id")
|
||||
if len(groupId) > 0 {
|
||||
q = q.Equals("cloudgroup_id", groupId)
|
||||
}
|
||||
if len(accountId) > 0 {
|
||||
q = q.Equals("cloudaccount_id", accountId)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// SAML认证用户列表
|
||||
func (manager *SSamluserManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query api.SamluserListInput) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusDomainLevelUserResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusDomainLevelUserResourceListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q, err = manager.SCloudgroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudgroupResourceListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q, err = manager.SCloudaccountResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudaccountResourceListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
// 创建SAML认证用户
|
||||
func (manager *SSamluserManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SamluserCreateInput) (api.SamluserCreateInput, error) {
|
||||
if len(input.OwnerId) > 0 {
|
||||
user, err := db.UserCacheManager.FetchUserById(ctx, input.OwnerId)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "FetchUserById")
|
||||
}
|
||||
input.OwnerId = user.Id
|
||||
input.Name = user.Name
|
||||
} else {
|
||||
input.OwnerId = userCred.GetUserId()
|
||||
input.Name = userCred.GetUserName()
|
||||
}
|
||||
_group, err := validators.ValidateModel(userCred, CloudgroupManager, &input.CloudgroupId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
group := _group.(*SCloudgroup)
|
||||
sq := CloudgroupManager.Query("id").Equals("provider", group.Provider).SubQuery()
|
||||
q := manager.Query().Equals("owner_id", input.OwnerId).In("cloudgroup_id", sq)
|
||||
groups := []SCloudgroup{}
|
||||
err = db.FetchModelObjects(CloudgroupManager, q, &groups)
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "db.FetchModelObjects"))
|
||||
}
|
||||
if len(groups) > 0 {
|
||||
return input, httperrors.NewConflictError("user %s has already in other %s group", input.Name, group.Provider)
|
||||
}
|
||||
_account, err := validators.ValidateModel(userCred, CloudaccountManager, &input.CloudaccountId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
account := _account.(*SCloudaccount)
|
||||
if account.Provider != group.Provider {
|
||||
return input, httperrors.NewConflictError("account %s and group %s not with same provider %s", account.Name, group.Name)
|
||||
}
|
||||
input.Status = api.SAML_USER_STATUS_AVAILABLE
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SSamluserManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.SamluserDetails {
|
||||
rows := make([]api.SamluserDetails, len(objs))
|
||||
userRows := manager.SStatusDomainLevelUserResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
groupRows := manager.SCloudgroupResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
acRows := manager.SCloudaccountResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = api.SamluserDetails{
|
||||
StatusDomainLevelUserResourceDetails: userRows[i],
|
||||
CloudgroupResourceDetails: groupRows[i],
|
||||
CloudaccountResourceDetails: acRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
@@ -23,8 +23,10 @@ type SCloudIdOptions struct {
|
||||
common_options.DBOptions
|
||||
|
||||
CloudaccountSyncIntervalMinutes int `help:"frequency to sync region cloudaccount task" default:"3"`
|
||||
SAMLProviderSyncIntervalHours int `help:"frequency to sync account saml provider task" default:"3"`
|
||||
SystemPoliciesSyncIntervalHours int `help:"frequency to sync region cloudaccount task" default:"24"`
|
||||
CloudIdResourceSyncIntervalHours int `help:"frequency to sync region cloudpolicy task" default:"3"`
|
||||
CloudroleSyncIntervalHours int `help:"frequency to sync region cloudroles task" default:"12"`
|
||||
|
||||
CloudSAMLMetadataPath string `help:"path to store SAML sp metadata file of cloud providers" default:"/opt/yunion/share/saml/sp-metadata"`
|
||||
}
|
||||
|
||||
@@ -13,3 +13,109 @@
|
||||
// limitations under the License.
|
||||
|
||||
package saml // import "yunion.io/x/onecloud/pkg/cloudid/saml"
|
||||
|
||||
/*
|
||||
|
||||
+-----------------+ +----------------+
|
||||
| CloudId Service | | Region Service |
|
||||
+-----------------+ +----------------+
|
||||
|
||||
|
||||
+----------+
|
||||
|EnableSaml|
|
||||
+-------------------+ +------------+ +----------+
|
||||
| Cloudaccount | |Cloudaccount|
|
||||
| (enabled|disable) | +------------+ +-----------+
|
||||
+----________-------+ |DisableSaml|
|
||||
_______/ \_______ +-----------+
|
||||
___/ \____
|
||||
+--------------+ +--------------+
|
||||
| SamlProvider | | SamlProvider |
|
||||
| (available) | | (not match) |
|
||||
+--------------+ +--------------+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Saml Check CronJob Task
|
||||
|
||||
+-------+
|
||||
| Start |
|
||||
+---|---+
|
||||
|
|
||||
|
|
||||
v
|
||||
+------------------------+ Yes +----------------------------------------+ No +---------------------+
|
||||
| Is account enable saml | ----------------> | Is account has available saml provider |----------------> | Create saml provider|
|
||||
+------------------------+ +----------------------------------------+ +---------------------+
|
||||
| | |
|
||||
| No | Yes |
|
||||
| | |
|
||||
v | |
|
||||
+------+ | |
|
||||
| End | <-----------------------------------------------<----------------------------------------------------
|
||||
+------+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Saml Auth Login
|
||||
|
||||
+-------+
|
||||
| Start |
|
||||
+-------+
|
||||
|
|
||||
|
|
||||
v
|
||||
+-----------------------+ Yes +-----------------------------------------------+
|
||||
|Is account enable saml |-------------> |Prepare tmp Role and set expired time for user |
|
||||
+-----------------------+ +-----------------------------------------------+
|
||||
| No |
|
||||
| |
|
||||
| |
|
||||
| v
|
||||
| +------------------+
|
||||
| | Auth for console |
|
||||
| +------------------+
|
||||
| |
|
||||
| |
|
||||
v |
|
||||
+------+ |
|
||||
| End |<----------------------------------------------
|
||||
+------+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
@@ -55,6 +56,7 @@ func initSAMLInstance() error {
|
||||
return errors.Wrap(err, "samlutils.NewSAMLInstance")
|
||||
}
|
||||
|
||||
models.SamlIdpInstance = SAMLIdpInstance
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -65,6 +67,10 @@ func SAMLInstance() *samlutils.SSAMLInstance {
|
||||
return saml
|
||||
}
|
||||
|
||||
func SAMLIdpInstance() *idp.SSAMLIdpInstance {
|
||||
return idpInstance
|
||||
}
|
||||
|
||||
func IsSAMLEnabled() bool {
|
||||
return saml != nil
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/saml/providers"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
@@ -38,11 +38,11 @@ func initSAMLIdp(app *appsrv.Application, prefix string) error {
|
||||
token := auth.FetchUserCredential(ctx, nil)
|
||||
log.Debugf("Recive SP initiated Login: %s", sp.GetEntityId())
|
||||
data := samlutils.SSAMLSpInitiatedLoginData{}
|
||||
driver := providers.FindDriver(sp.GetEntityId())
|
||||
driver := models.FindDriver(sp.GetEntityId())
|
||||
if driver == nil {
|
||||
return data, errors.Wrapf(httperrors.ErrResourceNotFound, "entityID %s not found", sp.GetEntityId())
|
||||
}
|
||||
data, err := driver.GetSpInitiatedLoginData(idpId, token.GetUserId(), sp)
|
||||
data, err := driver.GetSpInitiatedLoginData(ctx, token, idpId, sp)
|
||||
if err != nil {
|
||||
return data, errors.Wrap(err, "driver.GetSpInitiatedLoginData")
|
||||
}
|
||||
@@ -62,11 +62,11 @@ func initSAMLIdp(app *appsrv.Application, prefix string) error {
|
||||
token := auth.FetchUserCredential(ctx, nil)
|
||||
log.Debugf("Recive IDP initiated Login: %s", sp.GetEntityId())
|
||||
data := samlutils.SSAMLIdpInitiatedLoginData{}
|
||||
driver := providers.FindDriver(sp.GetEntityId())
|
||||
driver := models.FindDriver(sp.GetEntityId())
|
||||
if driver == nil {
|
||||
return data, errors.Wrapf(httperrors.ErrResourceNotFound, "entityID %s not found", sp.GetEntityId())
|
||||
}
|
||||
data, err := driver.GetIdpInitiatedLoginData(idpId, token.GetUserId(), sp)
|
||||
data, err := driver.GetIdpInitiatedLoginData(ctx, token, idpId, sp)
|
||||
if err != nil {
|
||||
return data, errors.Wrap(err, "driver.GetIdpInitiatedLoginData")
|
||||
}
|
||||
@@ -78,7 +78,7 @@ func initSAMLIdp(app *appsrv.Application, prefix string) error {
|
||||
}
|
||||
|
||||
idpInst := idp.NewIdpInstance(saml, spFunc, idpFunc, logoutFunc)
|
||||
for entityId, drvFactory := range providers.AllDrivers() {
|
||||
for entityId, drvFactory := range models.AllDrivers() {
|
||||
filePath := path.Join(options.Options.CloudSAMLMetadataPath, drvFactory.GetMetadataFilename())
|
||||
metaBytes, err := ioutil.ReadFile(filePath)
|
||||
if err != nil || len(metaBytes) == 0 {
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
)
|
||||
|
||||
func (d *SAliyunSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
func (d *SAliyunSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
// TODO
|
||||
data := samlutils.SSAMLIdpInitiatedLoginData{}
|
||||
data.NameId = "ecsossreadonly"
|
||||
@@ -41,7 +44,7 @@ func (d *SAliyunSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userI
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (d *SAliyunSAMLDriver) GetSpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
func (d *SAliyunSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
// not supported
|
||||
return samlutils.SSAMLSpInitiatedLoginData{}, errors.ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudid/saml/providers"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
@@ -34,5 +34,5 @@ func (d *SAliyunSAMLDriver) GetMetadataUrl() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
providers.Register(&SAliyunSAMLDriver{})
|
||||
models.Register(&SAliyunSAMLDriver{})
|
||||
}
|
||||
|
||||
@@ -15,17 +15,49 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
)
|
||||
|
||||
func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
// TODO
|
||||
func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
data := samlutils.SSAMLIdpInitiatedLoginData{}
|
||||
|
||||
data.NameId = "ec2s3readonly"
|
||||
_account, err := models.CloudaccountManager.FetchById(cloudAccountId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return data, httperrors.NewResourceNotFoundError("cloudaccount", cloudAccountId)
|
||||
}
|
||||
return data, httperrors.NewGeneralError(err)
|
||||
}
|
||||
account := _account.(*models.SCloudaccount)
|
||||
if account.Provider != api.CLOUD_PROVIDER_AWS {
|
||||
return data, httperrors.NewClientError("cloudaccount %s is %s not %s", account.Id, account.Provider, api.CLOUD_PROVIDER_AWS)
|
||||
}
|
||||
if account.SAMLAuth.IsFalse() {
|
||||
return data, httperrors.NewNotSupportedError("cloudaccount %s not open saml auth", account.Id)
|
||||
}
|
||||
|
||||
SAMLProvider, valid := account.IsSAMLProviderValid()
|
||||
if !valid {
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
|
||||
data.NameId = userCred.GetUserName()
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_PERSISTENT
|
||||
data.AudienceRestriction = "https://signin.aws.amazon.com/saml"
|
||||
for _, v := range []struct {
|
||||
@@ -36,17 +68,17 @@ func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId s
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/Role",
|
||||
friendlyName: "RoleEntitlement",
|
||||
value: "arn:aws:iam::285906155448:role/ec2s3readonly,arn:aws:iam::285906155448:saml-provider/saml.yunion.cn",
|
||||
value: fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
|
||||
},
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/RoleSessionName",
|
||||
friendlyName: "RoleSessionName",
|
||||
value: "ec2s3readonly",
|
||||
value: userCred.GetUserId(),
|
||||
},
|
||||
{
|
||||
name: "urn:oid:1.3.6.1.4.1.5923.1.1.1.3",
|
||||
friendlyName: "eduPersonOrgDN",
|
||||
value: "ec2s3readonly",
|
||||
value: userCred.GetUserName(),
|
||||
},
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
@@ -60,7 +92,7 @@ func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId s
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (d *SAWSSAMLDriver) GetSpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
func (d *SAWSSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
// not supported
|
||||
return samlutils.SSAMLSpInitiatedLoginData{}, errors.ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudid/saml/providers"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
@@ -34,5 +34,5 @@ func (d *SAWSSAMLDriver) GetMetadataUrl() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
providers.Register(&SAWSSAMLDriver{})
|
||||
models.Register(&SAWSSAMLDriver{})
|
||||
}
|
||||
|
||||
@@ -15,17 +15,48 @@
|
||||
package awscn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
)
|
||||
|
||||
func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
// TODO
|
||||
func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
data := samlutils.SSAMLIdpInitiatedLoginData{}
|
||||
_account, err := models.CloudaccountManager.FetchById(cloudAccountId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return data, httperrors.NewResourceNotFoundError("cloudaccount", cloudAccountId)
|
||||
}
|
||||
return data, httperrors.NewGeneralError(err)
|
||||
}
|
||||
account := _account.(*models.SCloudaccount)
|
||||
if account.Provider != api.CLOUD_PROVIDER_AWS {
|
||||
return data, httperrors.NewClientError("cloudaccount %s is %s not %s", account.Id, account.Provider, api.CLOUD_PROVIDER_AWS)
|
||||
}
|
||||
if account.SAMLAuth.IsFalse() {
|
||||
return data, httperrors.NewNotSupportedError("cloudaccount %s not open saml auth", account.Id)
|
||||
}
|
||||
|
||||
data.NameId = "ec2s3readonly"
|
||||
SAMLProvider, valid := account.IsSAMLProviderValid()
|
||||
if !valid {
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
|
||||
data.NameId = userCred.GetUserName()
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_PERSISTENT
|
||||
data.AudienceRestriction = "https://signin.amazonaws.cn/saml"
|
||||
for _, v := range []struct {
|
||||
@@ -36,17 +67,17 @@ func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/Role",
|
||||
friendlyName: "RoleEntitlement",
|
||||
value: "arn:aws-cn:iam::248697896586:role/ec2s3readonly,arn:aws-cn:iam::248697896586:saml-provider/saml.yunion.io",
|
||||
value: fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
|
||||
},
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/RoleSessionName",
|
||||
friendlyName: "RoleSessionName",
|
||||
value: "ec2s3readonly",
|
||||
value: userCred.GetUserId(),
|
||||
},
|
||||
{
|
||||
name: "urn:oid:1.3.6.1.4.1.5923.1.1.1.3",
|
||||
friendlyName: "eduPersonOrgDN",
|
||||
value: "ec2s3readonly",
|
||||
value: userCred.GetUserName(),
|
||||
},
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
@@ -60,7 +91,7 @@ func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (d *SAWSCNSAMLDriver) GetSpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
func (d *SAWSCNSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
// not supported
|
||||
return samlutils.SSAMLSpInitiatedLoginData{}, errors.ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package awscn
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudid/saml/providers"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
@@ -34,5 +34,5 @@ func (d *SAWSCNSAMLDriver) GetMetadataUrl() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
providers.Register(&SAWSCNSAMLDriver{})
|
||||
models.Register(&SAWSCNSAMLDriver{})
|
||||
}
|
||||
|
||||
@@ -15,19 +15,22 @@
|
||||
package google
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
)
|
||||
|
||||
func (d *SGoogleSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
func (d *SGoogleSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
// not supported
|
||||
data := samlutils.SSAMLIdpInitiatedLoginData{}
|
||||
|
||||
return data, httperrors.ErrNotSupported
|
||||
}
|
||||
|
||||
func (d *SGoogleSAMLDriver) GetSpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
func (d *SGoogleSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
// TODO
|
||||
data := samlutils.SSAMLSpInitiatedLoginData{}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudid/saml/providers"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
@@ -34,5 +34,5 @@ func (d *SGoogleSAMLDriver) GetMetadataUrl() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
providers.Register(&SGoogleSAMLDriver{})
|
||||
models.Register(&SGoogleSAMLDriver{})
|
||||
}
|
||||
|
||||
@@ -15,33 +15,68 @@
|
||||
package huawei
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
)
|
||||
|
||||
func (d *SHuaweiSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
func (d *SHuaweiSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
// not supported
|
||||
data := samlutils.SSAMLIdpInitiatedLoginData{}
|
||||
|
||||
return data, httperrors.ErrNotSupported
|
||||
}
|
||||
|
||||
func (d *SHuaweiSAMLDriver) GetSpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
// TODO
|
||||
func (d *SHuaweiSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
data := samlutils.SSAMLSpInitiatedLoginData{}
|
||||
|
||||
data.NameId = "yunionoss"
|
||||
_account, err := models.CloudaccountManager.FetchById(cloudAccountId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return data, httperrors.NewResourceNotFoundError("cloudaccount", cloudAccountId)
|
||||
}
|
||||
return data, httperrors.NewGeneralError(err)
|
||||
}
|
||||
account := _account.(*models.SCloudaccount)
|
||||
if account.Provider != api.CLOUD_PROVIDER_HUAWEI {
|
||||
return data, httperrors.NewClientError("cloudaccount %s is %s not %s", account.Id, account.Provider, api.CLOUD_PROVIDER_HUAWEI)
|
||||
}
|
||||
if account.SAMLAuth.IsFalse() {
|
||||
return data, httperrors.NewNotSupportedError("cloudaccount %s not open saml auth", account.Id)
|
||||
}
|
||||
|
||||
_, valid := account.IsSAMLProviderValid()
|
||||
if !valid {
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
groups, err := account.GetUserCloudgroups(userCred.GetUserId())
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "GetUserCloudgroups"))
|
||||
}
|
||||
if len(groups) == 0 {
|
||||
return data, httperrors.NewResourceNotFoundError("no available group found")
|
||||
}
|
||||
|
||||
data.NameId = userCred.GetUserName()
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
|
||||
data.AudienceRestriction = sp.GetEntityId()
|
||||
for k, v := range map[string]string{
|
||||
"User": "ec2admin",
|
||||
"Group": "ec2admin",
|
||||
for k, v := range map[string][]string{
|
||||
"User": []string{userCred.GetUserName()},
|
||||
"Groups": groups,
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
Name: k, FriendlyName: k,
|
||||
NameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
|
||||
Values: []string{v},
|
||||
Values: v,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package huawei
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudid/saml/providers"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
@@ -34,5 +34,5 @@ func (d *SHuaweiSAMLDriver) GetMetadataUrl() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
providers.Register(&SHuaweiSAMLDriver{})
|
||||
models.Register(&SHuaweiSAMLDriver{})
|
||||
}
|
||||
|
||||
@@ -15,15 +15,51 @@
|
||||
package qcloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
)
|
||||
|
||||
func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
// TODO
|
||||
func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error) {
|
||||
data := samlutils.SSAMLIdpInitiatedLoginData{}
|
||||
|
||||
data.NameId = "cvmcosreadonly"
|
||||
_account, err := models.CloudaccountManager.FetchById(cloudAccountId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return data, httperrors.NewResourceNotFoundError("cloudaccount", cloudAccountId)
|
||||
}
|
||||
return data, httperrors.NewGeneralError(err)
|
||||
}
|
||||
account := _account.(*models.SCloudaccount)
|
||||
if account.Provider != api.CLOUD_PROVIDER_QCLOUD {
|
||||
return data, httperrors.NewClientError("cloudaccount %s is %s not %s", account.Id, account.Provider, api.CLOUD_PROVIDER_QCLOUD)
|
||||
}
|
||||
if account.SAMLAuth.IsFalse() {
|
||||
return data, httperrors.NewNotSupportedError("cloudaccount %s not open saml auth", account.Id)
|
||||
}
|
||||
|
||||
SAMLProvider, valid := account.IsSAMLProviderValid()
|
||||
if !valid {
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
|
||||
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, role.ExternalId, account.AccountId, SAMLProvider.ExternalId)
|
||||
|
||||
data.NameId = role.Name
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
|
||||
data.AudienceRestriction = "https://cloud.tencent.com"
|
||||
for _, v := range []struct {
|
||||
@@ -34,12 +70,12 @@ func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userI
|
||||
{
|
||||
name: "https://cloud.tencent.com/SAML/Attributes/Role",
|
||||
friendlyName: "RoleEntitlement",
|
||||
value: "qcs::cam::uin/100008182714:roleName/cvmcosreadonly,qcs::cam::uin/100008182714:saml-provider/saml.yunion.io",
|
||||
value: roleStr,
|
||||
},
|
||||
{
|
||||
name: "https://cloud.tencent.com/SAML/Attributes/RoleSessionName",
|
||||
friendlyName: "RoleSessionName",
|
||||
value: "cvmcosreadonly",
|
||||
value: role.Name,
|
||||
},
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
@@ -53,11 +89,36 @@ func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(cloudAccoutId string, userI
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(cloudAccoutId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
// not supported
|
||||
func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCred mcclient.TokenCredential, cloudAccountId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error) {
|
||||
data := samlutils.SSAMLSpInitiatedLoginData{}
|
||||
_account, err := models.CloudaccountManager.FetchById(cloudAccountId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return data, httperrors.NewResourceNotFoundError("cloudaccount", cloudAccountId)
|
||||
}
|
||||
return data, httperrors.NewGeneralError(err)
|
||||
}
|
||||
account := _account.(*models.SCloudaccount)
|
||||
if account.Provider != api.CLOUD_PROVIDER_QCLOUD {
|
||||
return data, httperrors.NewClientError("cloudaccount %s is %s not %s", account.Id, account.Provider, api.CLOUD_PROVIDER_QCLOUD)
|
||||
}
|
||||
if account.SAMLAuth.IsFalse() {
|
||||
return data, httperrors.NewNotSupportedError("cloudaccount %s not open saml auth", account.Id)
|
||||
}
|
||||
|
||||
data.NameId = "cvmcosreadonly"
|
||||
SAMLProvider, valid := account.IsSAMLProviderValid()
|
||||
if !valid {
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
|
||||
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, role.ExternalId, account.AccountId, SAMLProvider.ExternalId)
|
||||
|
||||
data.NameId = role.Name
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
|
||||
data.AudienceRestriction = "https://cloud.tencent.com"
|
||||
for _, v := range []struct {
|
||||
@@ -68,12 +129,12 @@ func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(cloudAccoutId string, userId
|
||||
{
|
||||
name: "https://cloud.tencent.com/SAML/Attributes/Role",
|
||||
friendlyName: "RoleEntitlement",
|
||||
value: "qcs::cam::uin/100008182714:roleName/cvmcosreadonly,qcs::cam::uin/100008182714:saml-provider/saml.yunion.io",
|
||||
value: roleStr,
|
||||
},
|
||||
{
|
||||
name: "https://cloud.tencent.com/SAML/Attributes/RoleSessionName",
|
||||
friendlyName: "RoleSessionName",
|
||||
value: "cvmcosreadonly",
|
||||
value: role.Name,
|
||||
},
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package qcloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudid/saml/providers"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
@@ -34,5 +34,5 @@ func (d *SQcloudSAMLDriver) GetMetadataUrl() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
providers.Register(&SQcloudSAMLDriver{})
|
||||
models.Register(&SQcloudSAMLDriver{})
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.CloudgroupcacheManager,
|
||||
models.CloudpolicyManager,
|
||||
models.CloudpolicycacheManager,
|
||||
models.SAMLProviderManager,
|
||||
models.CloudroleManager,
|
||||
models.SamluserManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
|
||||
@@ -61,8 +61,10 @@ func StartService() {
|
||||
if !opts.IsSlaveNode {
|
||||
cron := cronman.InitCronJobManager(true, options.Options.CronJobWorkerCount)
|
||||
cron.AddJobAtIntervalsWithStartRun("SyncCloudaccounts", time.Duration(opts.CloudaccountSyncIntervalMinutes)*time.Minute, models.CloudaccountManager.SyncCloudaccounts, true)
|
||||
cron.AddJobAtIntervalsWithStartRun("SyncSAMLProviders", time.Duration(opts.SAMLProviderSyncIntervalHours)*time.Hour, models.CloudaccountManager.SyncSAMLProviders, true)
|
||||
cron.AddJobAtIntervalsWithStartRun("SyncSystemCloudpolicies", time.Duration(opts.SystemPoliciesSyncIntervalHours)*time.Hour, models.CloudaccountManager.SyncCloudidSystemPolicies, true)
|
||||
cron.AddJobAtIntervalsWithStartRun("SyncCloudIdResources", time.Duration(opts.CloudIdResourceSyncIntervalHours)*time.Hour, models.CloudaccountManager.SyncCloudidResources, true)
|
||||
cron.AddJobAtIntervalsWithStartRun("SyncCloudroles", time.Duration(opts.CloudroleSyncIntervalHours)*time.Hour, models.CloudaccountManager.SyncCloudroles, true)
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type CloudroleDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(CloudroleDeleteTask{})
|
||||
}
|
||||
|
||||
func (self *CloudroleDeleteTask) taskFailed(ctx context.Context, role *models.SCloudrole, err error) {
|
||||
role.SetStatus(self.GetUserCred(), api.CLOUD_ROLE_STATUS_DELETE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, role, logclient.ACT_DELETE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *CloudroleDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
role := obj.(*models.SCloudrole)
|
||||
|
||||
isPurge := jsonutils.QueryBoolean(self.Params, "purge", false)
|
||||
if len(role.ExternalId) == 0 || isPurge {
|
||||
role.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
return
|
||||
}
|
||||
|
||||
account, err := role.GetCloudaccount()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, role, errors.Wrapf(err, "GetCloudaccount"))
|
||||
return
|
||||
}
|
||||
provider, err := account.GetProvider()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, role, errors.Wrapf(err, "GetProvider"))
|
||||
return
|
||||
}
|
||||
iRole, err := provider.GetICloudroleById(role.ExternalId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
role.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
return
|
||||
}
|
||||
self.taskFailed(ctx, role, errors.Wrapf(err, "GetICloudroleById(%s)", role.ExternalId))
|
||||
return
|
||||
}
|
||||
err = iRole.Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, role, errors.Wrapf(err, "iRole.Delete"))
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type SAMLProviderCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(SAMLProviderCreateTask{})
|
||||
}
|
||||
|
||||
func (self *SAMLProviderCreateTask) taskFailed(ctx context.Context, saml *models.SSAMLProvider, err error) {
|
||||
saml.SetStatus(self.GetUserCred(), api.SAML_PROVIDER_STATUS_CREATE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, saml, logclient.ACT_CREATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *SAMLProviderCreateTask) taskComplete(ctx context.Context, saml *models.SSAMLProvider) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *SAMLProviderCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
saml := obj.(*models.SSAMLProvider)
|
||||
|
||||
metadata, err := saml.GetMetadataDocument()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrapf(err, "GetMetadataDocument"))
|
||||
return
|
||||
}
|
||||
|
||||
account, err := saml.GetCloudaccount()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrapf(err, "GetCloudaccount"))
|
||||
return
|
||||
}
|
||||
|
||||
provider, err := account.GetProvider()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrap(err, "GetProvider"))
|
||||
return
|
||||
}
|
||||
|
||||
opts := cloudprovider.SAMLProviderCreateOptions{
|
||||
Name: saml.Name,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
lockman.LockRawObject(ctx, saml.CloudaccountId, "saml-provider")
|
||||
defer lockman.ReleaseRawObject(ctx, saml.CloudaccountId, "saml-provider")
|
||||
|
||||
iSAMLProvider, err := provider.CreateICloudSAMLProvider(&opts)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrapf(err, "CreateICloudSAMLProvider"))
|
||||
return
|
||||
}
|
||||
|
||||
err = saml.SyncWithCloudSAMLProvider(ctx, self.GetUserCred(), iSAMLProvider)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrap(err, "SyncWithCloudSAMLProvider"))
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type SAMLProviderDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(SAMLProviderDeleteTask{})
|
||||
}
|
||||
|
||||
func (self *SAMLProviderDeleteTask) taskFailed(ctx context.Context, saml *models.SSAMLProvider, err error) {
|
||||
saml.SetStatus(self.GetUserCred(), api.SAML_PROVIDER_STATUS_DELETE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, saml, logclient.ACT_DELETE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *SAMLProviderDeleteTask) taskComplete(ctx context.Context, saml *models.SSAMLProvider) {
|
||||
saml.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *SAMLProviderDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
saml := obj.(*models.SSAMLProvider)
|
||||
|
||||
if len(saml.ExternalId) == 0 {
|
||||
self.taskComplete(ctx, saml)
|
||||
return
|
||||
}
|
||||
|
||||
account, err := saml.GetCloudaccount()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrapf(err, "GetCloudaccount"))
|
||||
return
|
||||
}
|
||||
|
||||
provider, err := account.GetProvider()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrapf(err, "GetProvider"))
|
||||
return
|
||||
}
|
||||
samls, err := provider.GetICloudSAMLProviders()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrapf(err, "GetICloudSAMLProviders"))
|
||||
return
|
||||
}
|
||||
|
||||
for i := range samls {
|
||||
if samls[i].GetGlobalId() == saml.ExternalId {
|
||||
err = samls[i].Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, saml, errors.Wrapf(err, "Delete"))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.taskComplete(ctx, saml)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
)
|
||||
|
||||
type SyncCloudrolesTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(SyncCloudrolesTask{})
|
||||
}
|
||||
|
||||
func (self *SyncCloudrolesTask) taskFailed(ctx context.Context, account *models.SCloudaccount, err error) {
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *SyncCloudrolesTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
account := obj.(*models.SCloudaccount)
|
||||
|
||||
provider, err := account.GetProvider()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, account, errors.Wrapf(err, "GetProvider"))
|
||||
return
|
||||
}
|
||||
|
||||
roles, err := provider.GetICloudroles()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, account, errors.Wrapf(err, "GetICloudroles"))
|
||||
return
|
||||
}
|
||||
result := account.SyncCloudroles(ctx, self.GetUserCred(), roles)
|
||||
log.Infof("SyncCloudroles for account %s(%s) result: %s", account.Name, account.Provider, result.Result())
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/models"
|
||||
)
|
||||
|
||||
type SyncSAMLProvidersTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(SyncSAMLProvidersTask{})
|
||||
}
|
||||
|
||||
func (self *SyncSAMLProvidersTask) taskFailed(ctx context.Context, account *models.SCloudaccount, err error) {
|
||||
log.Errorf("failed sync saml provider for account %s error: %v", account.Name, err)
|
||||
self.SetStageFailed(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *SyncSAMLProvidersTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
account := obj.(*models.SCloudaccount)
|
||||
|
||||
provider, err := account.GetProvider()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, account, errors.Wrapf(err, "GetProvider"))
|
||||
return
|
||||
}
|
||||
|
||||
lockman.LockRawObject(ctx, account.Id, "saml-provider")
|
||||
defer lockman.ReleaseRawObject(ctx, account.Id, "saml-provider")
|
||||
|
||||
samls, err := provider.GetICloudSAMLProviders()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, account, errors.Wrapf(err, "GetICloudSAMLProviders"))
|
||||
return
|
||||
}
|
||||
|
||||
result := account.SyncSAMLProviders(ctx, self.GetUserCred(), samls)
|
||||
log.Infof("Sync SAMLProviders for account %s(%s) result: %s", account.Name, account.Provider, result.Result())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -153,6 +153,8 @@ type ProviderConfig struct {
|
||||
Account string
|
||||
Secret string
|
||||
|
||||
AccountId string
|
||||
|
||||
ProxyFunc httputils.TransportProxyFunc
|
||||
}
|
||||
|
||||
@@ -223,6 +225,8 @@ type ICloudProviderFactory interface {
|
||||
GetSupportedDnsPolicyTypes() map[TDnsZoneType][]TDnsPolicyType
|
||||
GetSupportedDnsPolicyValues() map[TDnsPolicyType][]TDnsPolicyValue
|
||||
GetTTLRange(zoneType TDnsZoneType, productType TDnsProductType) TTlRange
|
||||
|
||||
IsSupportSAMLAuth() bool
|
||||
}
|
||||
|
||||
type ICloudProvider interface {
|
||||
@@ -264,6 +268,12 @@ type ICloudProvider interface {
|
||||
CreateICloudgroup(name, desc string) (ICloudgroup, error)
|
||||
GetIClouduserByName(name string) (IClouduser, error)
|
||||
CreateIClouduser(conf *SClouduserCreateConfig) (IClouduser, error)
|
||||
CreateICloudSAMLProvider(opts *SAMLProviderCreateOptions) (ICloudSAMLProvider, error)
|
||||
GetICloudSAMLProviders() ([]ICloudSAMLProvider, error)
|
||||
GetICloudroles() ([]ICloudrole, error)
|
||||
GetICloudroleById(id string) (ICloudrole, error)
|
||||
GetICloudroleByName(name string) (ICloudrole, error)
|
||||
CreateICloudrole(opts *SRoleCreateOptions) (ICloudrole, error)
|
||||
|
||||
CreateICloudpolicy(opts *SCloudpolicyCreateOptions) (ICloudpolicy, error)
|
||||
|
||||
@@ -271,7 +281,6 @@ type ICloudProvider interface {
|
||||
CreateSubscription(SubscriptionCreateInput) error
|
||||
|
||||
GetSamlEntityId() string
|
||||
GetSamlSpInitiatedLoginUrl(idpName string) string
|
||||
|
||||
GetICloudDnsZones() ([]ICloudDnsZone, error)
|
||||
GetICloudDnsZoneById(id string) (ICloudDnsZone, error)
|
||||
@@ -428,6 +437,30 @@ func (self *SBaseProvider) CreateIClouduser(conf *SClouduserCreateConfig) (IClou
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) GetICloudSAMLProviders() ([]ICloudSAMLProvider, error) {
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "GetICloudSAMLProviders")
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) GetICloudroles() ([]ICloudrole, error) {
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "GetICloudroles")
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) GetICloudroleById(id string) (ICloudrole, error) {
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "GetICloudroleById")
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) GetICloudroleByName(name string) (ICloudrole, error) {
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "GetICloudroleByName")
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) CreateICloudrole(opts *SRoleCreateOptions) (ICloudrole, error) {
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "CreateICloudrole")
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) CreateICloudSAMLProvider(opts *SAMLProviderCreateOptions) (ICloudSAMLProvider, error) {
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "CreateICloudSAMLProvider")
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) CreateICloudpolicy(opts *SCloudpolicyCreateOptions) (ICloudpolicy, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
@@ -464,10 +497,6 @@ func (self *SBaseProvider) GetSamlEntityId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SBaseProvider) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func NewBaseProvider(factory ICloudProviderFactory) SBaseProvider {
|
||||
return SBaseProvider{factory: factory}
|
||||
}
|
||||
@@ -557,6 +586,10 @@ func (factory *baseProviderFactory) GetSupportedBrands() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (factory *baseProviderFactory) IsSupportSAMLAuth() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (factory *baseProviderFactory) GetProvider(providerId, providerName, url, username, password string) (ICloudProvider, error) {
|
||||
return nil, httperrors.NewNotImplementedError("Not Implemented GetProvider")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudprovider
|
||||
|
||||
type SRoleCreateOptions struct {
|
||||
Name string
|
||||
Desc string
|
||||
SAMLProvider string
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
)
|
||||
|
||||
type ICloudResource interface {
|
||||
@@ -1101,6 +1102,28 @@ type ICloudVpcPeeringConnection interface {
|
||||
GetPeerVpcId() string
|
||||
GetPeerAccountId() string
|
||||
GetEnabled() bool
|
||||
Delete() error
|
||||
}
|
||||
|
||||
type ICloudSAMLProvider interface {
|
||||
ICloudResource
|
||||
|
||||
GetMetadataDocument() (*samlutils.EntityDescriptor, error)
|
||||
|
||||
GetAuthUrl() string
|
||||
Delete() error
|
||||
}
|
||||
|
||||
type ICloudrole interface {
|
||||
GetGlobalId() string
|
||||
GetName() string
|
||||
|
||||
GetDocument() *jsonutils.JSONDict
|
||||
GetSAMLProvider() string
|
||||
|
||||
GetICloudpolicies() ([]ICloudpolicy, error)
|
||||
AttachPolicy(id string) error
|
||||
DetachPolicy(id string) error
|
||||
|
||||
Delete() error
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
package cloudprovider
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
|
||||
const (
|
||||
SAML_ENTITY_ID_ALIYUN_ROLE = "urn:alibaba:cloudcomputing"
|
||||
SAML_ENTITY_ID_AWS_CN = "urn:amazon:webservices:cn-north-1"
|
||||
@@ -22,3 +24,8 @@ const (
|
||||
SAML_ENTITY_ID_HUAWEI_CLOUD = "https://auth.huaweicloud.com/"
|
||||
SAML_ENTITY_ID_GOOGLE = "google.com"
|
||||
)
|
||||
|
||||
type SAMLProviderCreateOptions struct {
|
||||
Name string
|
||||
Metadata samlutils.EntityDescriptor
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -27,8 +26,9 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
)
|
||||
|
||||
func (account *SCloudaccount) AllowGetDetailsSaml(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
@@ -38,6 +38,10 @@ func (account *SCloudaccount) AllowGetDetailsSaml(ctx context.Context, userCred
|
||||
func (account *SCloudaccount) GetDetailsSaml(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (api.GetCloudaccountSamlOutput, error) {
|
||||
output := api.GetCloudaccountSamlOutput{}
|
||||
|
||||
if account.SAMLAuth.IsFalse() {
|
||||
return output, httperrors.NewNotSupportedError("account %s not enable saml auth", account.Name)
|
||||
}
|
||||
|
||||
provider, err := account.GetProvider()
|
||||
if err != nil {
|
||||
return output, errors.Wrap(err, "GetProviderFactory")
|
||||
@@ -50,18 +54,19 @@ func (account *SCloudaccount) GetDetailsSaml(ctx context.Context, userCred mccli
|
||||
output.RedirectLoginUrl = httputils.JoinPath(options.Options.ApiServer, cloudid.SAML_IDP_PREFIX, "redirect/login", account.Id)
|
||||
output.RedirectLogoutUrl = httputils.JoinPath(options.Options.ApiServer, cloudid.SAML_IDP_PREFIX, "redirect/logout", account.Id)
|
||||
output.MetadataUrl = httputils.JoinPath(options.Options.ApiServer, cloudid.SAML_IDP_PREFIX, "metadata", account.Id)
|
||||
// XXXXX
|
||||
// TODO, find idpName for this cloudaccount
|
||||
// XXXXX
|
||||
idpName := "saml.yunion.io"
|
||||
output.InitLoginUrl = provider.GetSamlSpInitiatedLoginUrl(idpName)
|
||||
if len(output.InitLoginUrl) == 0 {
|
||||
input := samlutils.SIdpInitiatedLoginInput{
|
||||
EntityID: output.EntityId,
|
||||
IdpId: account.Id,
|
||||
}
|
||||
output.InitLoginUrl = httputils.JoinPath(options.Options.ApiServer, cloudid.SAML_IDP_PREFIX, fmt.Sprintf("sso?%s", jsonutils.Marshal(input).QueryString()))
|
||||
s := auth.GetAdminSession(ctx, options.Options.Region, "")
|
||||
params := map[string]string{
|
||||
"scope": "system",
|
||||
"cloudaccount_id": account.Id,
|
||||
"status": cloudid.SAML_PROVIDER_STATUS_AVAILABLE,
|
||||
}
|
||||
samlproviders, _ := modules.SAMLProviders.List(s, jsonutils.Marshal(params))
|
||||
for _, sp := range samlproviders.Data {
|
||||
authUrl, _ := sp.GetString("auth_url")
|
||||
if len(authUrl) > 0 {
|
||||
output.InitLoginUrl = authUrl
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
@@ -163,6 +163,8 @@ type SCloudaccount struct {
|
||||
|
||||
// 公有云子账号登录地址
|
||||
IamLoginUrl string `width:"512" charset:"ascii" nullable:"false" list:"domain" update:"domain"`
|
||||
|
||||
SAMLAuth tristate.TriState `nullable:"false" get:"user" update:"domain" create:"optional" list:"user" default:"false"`
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetCloudproviders() []SCloudprovider {
|
||||
@@ -993,6 +995,9 @@ func (manager *SCloudaccountManager) validateCreateData(
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
if input.SAMLAuth != nil && *input.SAMLAuth && !providerDriver.IsSupportSAMLAuth() {
|
||||
return input, httperrors.NewNotSupportedError("%s not support saml auth", input.Provider)
|
||||
}
|
||||
if len(input.Brand) > 0 && input.Brand != providerDriver.GetName() {
|
||||
brands := providerDriver.GetSupportedBrands()
|
||||
if !utils.IsInStringArray(providerDriver.GetName(), brands) {
|
||||
|
||||
@@ -12,23 +12,24 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package providers
|
||||
package modules
|
||||
|
||||
var (
|
||||
driverTable = make(map[string]ICloudSAMLLoginDriver)
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
func Register(driver ICloudSAMLLoginDriver) {
|
||||
driverTable[driver.GetEntityID()] = driver
|
||||
type SCloudroleManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
func FindDriver(entityId string) ICloudSAMLLoginDriver {
|
||||
if driver, ok := driverTable[entityId]; ok {
|
||||
return driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
Cloudroles SCloudroleManager
|
||||
)
|
||||
|
||||
func AllDrivers() map[string]ICloudSAMLLoginDriver {
|
||||
return driverTable
|
||||
func init() {
|
||||
Cloudroles = SCloudroleManager{NewCloudIdManager("cloudrole", "cloudroles",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
register(&Cloudroles)
|
||||
}
|
||||
@@ -12,19 +12,24 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package providers
|
||||
package modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils/idp"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
type ICloudSAMLLoginDriver interface {
|
||||
GetEntityID() string
|
||||
|
||||
GetMetadataFilename() string
|
||||
GetMetadataUrl() string
|
||||
|
||||
GetIdpInitiatedLoginData(idpId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLIdpInitiatedLoginData, error)
|
||||
GetSpInitiatedLoginData(idpId string, userId string, sp *idp.SSAMLServiceProvider) (samlutils.SSAMLSpInitiatedLoginData, error)
|
||||
type SSAMLProviderManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
SAMLProviders SSAMLProviderManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
SAMLProviders = SSAMLProviderManager{NewCloudIdManager("saml_provider", "saml_providers",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
register(&SAMLProviders)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
type SSamluserManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
Samlusers SClouduserManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
Samlusers = SClouduserManager{NewCloudIdManager("samluser", "samlusers",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
register(&Samlusers)
|
||||
}
|
||||
@@ -464,6 +464,7 @@ type SCloudAccountUpdateBaseOptions struct {
|
||||
SyncIntervalSeconds *int `help:"auto synchornize interval in seconds"`
|
||||
AutoCreateProject *bool `help:"automatically create local project for new remote project"`
|
||||
ProxySetting string `help:"proxy setting name or id" json:"proxy_setting"`
|
||||
SamlAuth string `help:"Enable or disable saml auth" choices:"true|false"`
|
||||
|
||||
Desc string `help:"Description" json:"description" token:"desc"`
|
||||
}
|
||||
|
||||
@@ -12,12 +12,16 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package options
|
||||
package cloudid
|
||||
|
||||
import "yunion.io/x/jsonutils"
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type CloudgroupListOptions struct {
|
||||
BaseListOptions
|
||||
options.BaseListOptions
|
||||
|
||||
ClouduserId string `json:"clouduser_id"`
|
||||
CloudpolicyId string `json:"cloudpolicy_id"`
|
||||
@@ -25,7 +29,7 @@ type CloudgroupListOptions struct {
|
||||
}
|
||||
|
||||
func (opts *CloudgroupListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return ListStructToParams(opts)
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type CloudgroupCreateOptions struct {
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type CloudgroupcacheListOptions struct {
|
||||
options.BaseListOptions
|
||||
|
||||
CloudgroupId string `json:"cloudgroup_id"`
|
||||
}
|
||||
|
||||
func (opts *CloudgroupcacheListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type CloudgroupcacheIdOption struct {
|
||||
ID string `help:"Cloudgroup cache Id"`
|
||||
}
|
||||
|
||||
func (opts *CloudgroupcacheIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *CloudgroupcacheIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type CloudgroupPolicyListOptions struct {
|
||||
options.BaseListOptions
|
||||
Cloudgroup string `help:"ID or Name of Cloudgroup"`
|
||||
Cloudpolicy string `help:"Policy ID or name"`
|
||||
}
|
||||
|
||||
func (opts *CloudgroupPolicyListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
func (opts *CloudgroupPolicyListOptions) GetContextId() string {
|
||||
return opts.Cloudgroup
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type CloudgroupUserListOptions struct {
|
||||
options.BaseListOptions
|
||||
Cloudgroup string `help:"ID or Name of Cloudgroup"`
|
||||
Clouduser string `help:"User ID or name"`
|
||||
}
|
||||
|
||||
func (opts *CloudgroupUserListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
func (opts *CloudgroupUserListOptions) GetContextId() string {
|
||||
return opts.Clouduser
|
||||
}
|
||||
@@ -12,15 +12,17 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package options
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type CloudpolicyListOptions struct {
|
||||
BaseListOptions
|
||||
options.BaseListOptions
|
||||
|
||||
CloudproviderId string `json:"cloudprovider_id"`
|
||||
ClouduserId string `json:"clouduser_id"`
|
||||
@@ -29,7 +31,7 @@ type CloudpolicyListOptions struct {
|
||||
}
|
||||
|
||||
func (opts *CloudpolicyListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return ListStructToParams(opts)
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type CloudpolicyIdOptions struct {
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type CloudpolicycacheListOptions struct {
|
||||
options.BaseListOptions
|
||||
|
||||
CloudpolyId string
|
||||
CloudaccountId string
|
||||
}
|
||||
|
||||
func (opts *CloudpolicycacheListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type CloudroleListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *CloudroleListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type CloudroleIdOptions struct {
|
||||
ID string `help:"Cloudrole Id"`
|
||||
}
|
||||
|
||||
func (opts *CloudroleIdOptions) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *CloudroleIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -12,12 +12,16 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package options
|
||||
package cloudid
|
||||
|
||||
import "yunion.io/x/jsonutils"
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type ClouduserListOptions struct {
|
||||
BaseListOptions
|
||||
options.BaseListOptions
|
||||
CloudaccountId string `help:"Cloudaccount Id"`
|
||||
CloudproviderId string `help:"Cloudprovider Id"`
|
||||
CloudpolicyId string `help:"filter cloudusers by cloudpolicy"`
|
||||
@@ -25,7 +29,7 @@ type ClouduserListOptions struct {
|
||||
}
|
||||
|
||||
func (opts *ClouduserListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return ListStructToParams(opts)
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type ClouduserCreateOptions struct {
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type ClouduserPolicyListOptions struct {
|
||||
options.BaseListOptions
|
||||
Clouduser string `help:"ID or Name of Clouduser"`
|
||||
Cloudpolicy string `help:"Policy ID or name"`
|
||||
}
|
||||
|
||||
func (opts *ClouduserPolicyListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
func (opts *ClouduserPolicyListOptions) GetContextId() string {
|
||||
return opts.Cloudpolicy
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package cloudid // import "yunion.io/x/onecloud/pkg/mcclient/options/cloudid"
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type SAMLProviderListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *SAMLProviderListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type SAMLProviderIdOptions struct {
|
||||
ID string `help:"SAML Provider Id"`
|
||||
}
|
||||
|
||||
func (opts *SAMLProviderIdOptions) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *SAMLProviderIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type SAMLProviderCreateOptions struct {
|
||||
CLOUDACCOUNT_ID string
|
||||
}
|
||||
|
||||
func (opts *SAMLProviderCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudid
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type SamluserListOptions struct {
|
||||
options.BaseListOptions
|
||||
CloudgroupId string `help:"Filter by cloudgroup"`
|
||||
CloudaccountId string `help:"Filter by cloudaccount"`
|
||||
}
|
||||
|
||||
func (opts *SamluserListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type SamluserCreateOptions struct {
|
||||
OwnerId string
|
||||
CLOUDGROUP_ID string `help:"CloudgroupId"`
|
||||
CLOUDACCOUNT_ID string `help:"CloudaccountId"`
|
||||
}
|
||||
|
||||
func (opts *SamluserCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type SamluserIdOptions struct {
|
||||
ID string `help:"SAML user Id"`
|
||||
}
|
||||
|
||||
func (opts *SamluserIdOptions) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *SamluserIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -329,10 +329,6 @@ func (self *SAliyunProvider) GetSamlEntityId() string {
|
||||
return cloudprovider.SAML_ENTITY_ID_ALIYUN_ROLE
|
||||
}
|
||||
|
||||
func (self *SAliyunProvider) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SAliyunProvider) GetICloudDnsZones() ([]cloudprovider.ICloudDnsZone, error) {
|
||||
izones := []cloudprovider.ICloudDnsZone{}
|
||||
privateZone, err := self.client.GetPrivateICloudDnsZones()
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SAMLProvider struct {
|
||||
multicloud.SResourceBase
|
||||
client *SAliyunClient
|
||||
}
|
||||
|
||||
func (self *SAliyunClient) ListSAMLProviders() ([]SAMLProvider, error) {
|
||||
result := []SAMLProvider{}
|
||||
resp, err := self.ramRequest("ListSAMLProviders", map[string]string{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListSAMLProviders")
|
||||
}
|
||||
log.Errorf("result: %s", resp.PrettyString())
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SamlProviderListOptions struct {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&SamlProviderListOptions{}, "saml-provider-list", "List saml provider", func(cli *aliyun.SRegion, args *SamlProviderListOptions) error {
|
||||
result, err := cli.GetClient().ListSAMLProviders()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -16,9 +16,18 @@ package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
var (
|
||||
samlRole = `{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"sts:AssumeRoleWithSAML","Principal":{"Federated":"%s"},"Condition":{"StringEquals":{"SAML:aud":["%s"]}}}]}`
|
||||
)
|
||||
|
||||
type SRole struct {
|
||||
@@ -34,6 +43,78 @@ type SRole struct {
|
||||
CreateDate time.Time `xml:"CreateDate"`
|
||||
}
|
||||
|
||||
func (self *SRole) GetGlobalId() string {
|
||||
return self.Arn
|
||||
}
|
||||
|
||||
func (self *SRole) GetName() string {
|
||||
return self.RoleName
|
||||
}
|
||||
|
||||
func (self *SRole) Delete() error {
|
||||
return self.client.DeleteRole(self.RoleName)
|
||||
}
|
||||
|
||||
func (self *SRole) GetDocument() *jsonutils.JSONDict {
|
||||
data, err := url.QueryUnescape(self.AssumeRolePolicyDocument)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
document, err := jsonutils.Parse([]byte(data))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return document.(*jsonutils.JSONDict)
|
||||
}
|
||||
|
||||
//[{"Action":"sts:AssumeRoleWithSAML","Condition":{"StringEquals":{"SAML:aud":"https://signin.aws.amazon.com/saml"}},"Effect":"Allow","Principal":{"Federated":"arn:aws:iam::879324515906:saml-provider/quxuan"}}]
|
||||
func (self *SRole) GetSAMLProvider() string {
|
||||
document := self.GetDocument()
|
||||
if document != nil {
|
||||
statement, err := document.GetArray("Statement")
|
||||
if err == nil {
|
||||
for i := range statement {
|
||||
if action, _ := statement[i].GetString("Action"); action == "sts:AssumeRoleWithSAML" {
|
||||
sp, _ := statement[i].GetString("Principal", "Federated")
|
||||
if len(sp) > 0 {
|
||||
return sp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SRole) AttachPolicy(id string) error {
|
||||
return self.client.AttachRolePolicy(self.RoleName, self.client.getIamArn(id))
|
||||
}
|
||||
|
||||
func (self *SRole) DetachPolicy(id string) error {
|
||||
return self.client.DetachRolePolicy(self.RoleName, self.client.getIamArn(id))
|
||||
}
|
||||
|
||||
func (self *SRole) GetICloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
|
||||
policies := []SAttachedPolicy{}
|
||||
marker := ""
|
||||
for {
|
||||
part, err := self.client.ListAttachedRolePolicies(self.RoleName, marker, 100, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListAttachedRolePolicies")
|
||||
}
|
||||
policies = append(policies, part.AttachedPolicies...)
|
||||
marker = part.Marker
|
||||
if len(marker) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
ret := []cloudprovider.ICloudpolicy{}
|
||||
for i := range policies {
|
||||
ret = append(ret, &policies[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type SRoles struct {
|
||||
Roles []SRole `xml:"Roles>member"`
|
||||
IsTruncated bool `xml:"IsTruncated"`
|
||||
@@ -81,3 +162,48 @@ func (self *SAwsClient) DeleteRole(name string) error {
|
||||
}
|
||||
return self.iamRequest("DeleteRole", params, nil)
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetICloudroles() ([]cloudprovider.ICloudrole, error) {
|
||||
roles := []SRole{}
|
||||
marker := ""
|
||||
for {
|
||||
part, err := self.ListRoles(marker, 100, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListRoles")
|
||||
}
|
||||
roles = append(roles, part.Roles...)
|
||||
marker = part.Marker
|
||||
if len(marker) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
ret := []cloudprovider.ICloudrole{}
|
||||
for i := range roles {
|
||||
ret = append(ret, &roles[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SAwsClient) CreateRole(opts *cloudprovider.SRoleCreateOptions) (*SRole, error) {
|
||||
if len(opts.SAMLProvider) > 0 {
|
||||
aud := "https://signin.amazonaws.cn/saml"
|
||||
if self.GetAccessEnv() == api.CLOUD_ACCESS_ENV_AWS_GLOBAL {
|
||||
aud = "https://signin.aws.amazon.com/saml"
|
||||
}
|
||||
params := map[string]string{
|
||||
"RoleName": opts.Name,
|
||||
"Description": opts.Desc,
|
||||
"AssumeRolePolicyDocument": fmt.Sprintf(samlRole, opts.SAMLProvider, aud),
|
||||
}
|
||||
role := struct {
|
||||
Role SRole
|
||||
}{}
|
||||
err := self.iamRequest("CreateRole", params, &role)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateRole")
|
||||
}
|
||||
role.Role.client = self
|
||||
return &role.Role, nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -312,16 +312,59 @@ func (self *SAwsProvider) GetSamlEntityId() string {
|
||||
return self.client.GetSamlEntityId()
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetICloudDnsZones() ([]cloudprovider.ICloudDnsZone, error) {
|
||||
return self.client.GetICloudDnsZones()
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetICloudDnsZoneById(id string) (cloudprovider.ICloudDnsZone, error) {
|
||||
return self.client.GetHostedZoneById(id)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) CreateICloudDnsZone(opts *cloudprovider.SDnsZoneCreateOptions) (cloudprovider.ICloudDnsZone, error) {
|
||||
return self.client.CreateHostedZone(opts)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) {
|
||||
return self.client.GetICloudSAMLProviders()
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) CreateICloudSAMLProvider(opts *cloudprovider.SAMLProviderCreateOptions) (cloudprovider.ICloudSAMLProvider, error) {
|
||||
sp, err := self.client.CreateSAMLProvider(opts.Name, opts.Metadata.String())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CreateSAMLProvider")
|
||||
}
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetICloudroles() ([]cloudprovider.ICloudrole, error) {
|
||||
return self.client.GetICloudroles()
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetICloudroleById(id string) (cloudprovider.ICloudrole, error) {
|
||||
roles, err := self.GetICloudroles()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetICloudroles")
|
||||
}
|
||||
for i := range roles {
|
||||
if roles[i].GetGlobalId() == id {
|
||||
return roles[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetICloudroleByName(name string) (cloudprovider.ICloudrole, error) {
|
||||
role, err := self.client.GetRole(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetRole(%s)", name)
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) CreateICloudrole(opts *cloudprovider.SRoleCreateOptions) (cloudprovider.ICloudrole, error) {
|
||||
role, err := self.client.CreateRole(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateRole")
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
compute_api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudid/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
)
|
||||
|
||||
type SAMLProvider struct {
|
||||
multicloud.SResourceBase
|
||||
client *SAwsClient
|
||||
|
||||
SAMLMetadataDocument string `xml:"SAMLMetadataDocument"`
|
||||
Arn string `xml:"Arn"`
|
||||
ValidUntil time.Time `xml:"ValidUntil"`
|
||||
CreateDate time.Time `xml:"CreateDate"`
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetGlobalId() string {
|
||||
return self.Arn
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetId() string {
|
||||
return self.Arn
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetName() string {
|
||||
if info := strings.Split(self.Arn, "/"); len(info) > 0 {
|
||||
return info[len(info)-1]
|
||||
}
|
||||
return self.Arn
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetStatus() string {
|
||||
return api.SAML_PROVIDER_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) Delete() error {
|
||||
return self.client.DeleteSAMLProvider(self.Arn)
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetAuthUrl() string {
|
||||
input := samlutils.SIdpInitiatedLoginInput{
|
||||
EntityID: cloudprovider.SAML_ENTITY_ID_AWS_CN,
|
||||
IdpId: self.client.cpcfg.AccountId,
|
||||
}
|
||||
if self.client.GetAccessEnv() == compute_api.CLOUD_ACCESS_ENV_AWS_GLOBAL {
|
||||
input.EntityID = cloudprovider.SAML_ENTITY_ID_AWS
|
||||
}
|
||||
return httputils.JoinPath(options.Options.ApiServer, cloudid.SAML_IDP_PREFIX, fmt.Sprintf("sso?%s", jsonutils.Marshal(input).QueryString()))
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetMetadataDocument() (*samlutils.EntityDescriptor, error) {
|
||||
saml, err := self.client.GetSAMLProvider(self.Arn)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProvider(%s)", self.Arn)
|
||||
}
|
||||
metadata, err := samlutils.ParseMetadata([]byte(saml.SAMLMetadataDocument))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ParseMetadata")
|
||||
}
|
||||
return &metadata, nil
|
||||
}
|
||||
|
||||
type SAMLProviders struct {
|
||||
SAMLProviderList []SAMLProvider `xml:"SAMLProviderList>member"`
|
||||
}
|
||||
|
||||
func (self *SAwsClient) ListSAMLProviders() ([]SAMLProvider, error) {
|
||||
result := SAMLProviders{}
|
||||
err := self.iamRequest("ListSAMLProviders", nil, &result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListSAMLProviders")
|
||||
}
|
||||
return result.SAMLProviderList, nil
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetSAMLProvider(arn string) (*SAMLProvider, error) {
|
||||
result := &SAMLProvider{client: self, Arn: arn}
|
||||
params := map[string]string{"SAMLProviderArn": arn}
|
||||
err := self.iamRequest("GetSAMLProvider", params, result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProvider")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SAwsClient) DeleteSAMLProvider(arn string) error {
|
||||
params := map[string]string{"SAMLProviderArn": arn}
|
||||
return self.iamRequest("DeleteSAMLProvider", params, nil)
|
||||
}
|
||||
|
||||
func (self *SAwsClient) CreateSAMLProvider(name, metadata string) (*SAMLProvider, error) {
|
||||
name = func() string {
|
||||
ret := ""
|
||||
for _, s := range name {
|
||||
if unicode.IsLetter(s) || unicode.IsNumber(s) || s == '.' || s == '_' || s == '-' {
|
||||
ret += string(s)
|
||||
} else {
|
||||
ret += "-"
|
||||
}
|
||||
}
|
||||
if len(ret) > 128 {
|
||||
ret = ret[:128]
|
||||
}
|
||||
return ret
|
||||
}()
|
||||
params := map[string]string{
|
||||
"Name": name,
|
||||
"SAMLMetadataDocument": metadata,
|
||||
}
|
||||
result := struct {
|
||||
SAMLProviderArn string `xml:"SAMLProviderArn"`
|
||||
}{}
|
||||
err := self.iamRequest("CreateSAMLProvider", params, &result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateSAMLProvider")
|
||||
}
|
||||
return self.GetSAMLProvider(result.SAMLProviderArn)
|
||||
}
|
||||
|
||||
func (self *SAwsClient) UpdateSAMLProvider(arn, metadata string) (*SAMLProvider, error) {
|
||||
params := map[string]string{
|
||||
"SAMLProviderArn": arn,
|
||||
"SAMLMetadataDocument": metadata,
|
||||
}
|
||||
saml := &SAMLProvider{client: self}
|
||||
err := self.iamRequest("UpdateSAMLProvider", params, saml)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "UpdateSAMLProvider")
|
||||
}
|
||||
return saml, nil
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) {
|
||||
providers, err := self.ListSAMLProviders()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListSAMLProviders")
|
||||
}
|
||||
ret := []cloudprovider.ICloudSAMLProvider{}
|
||||
for i := range providers {
|
||||
providers[i].client = self
|
||||
ret = append(ret, &providers[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
@@ -44,6 +45,10 @@ func init() {
|
||||
return err
|
||||
}
|
||||
printObject(role)
|
||||
document := role.GetDocument()
|
||||
if document != nil {
|
||||
printObject(document)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -51,4 +56,13 @@ func init() {
|
||||
return cli.GetClient().DeleteRole(args.ROLE)
|
||||
})
|
||||
|
||||
shellutils.R(&cloudprovider.SRoleCreateOptions{}, "cloud-role-create", "Create role", func(cli *aws.SRegion, args *cloudprovider.SRoleCreateOptions) error {
|
||||
role, err := cli.GetClient().CreateRole(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(role)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SAMLProviderListOptions struct {
|
||||
}
|
||||
shellutils.R(&SAMLProviderListOptions{}, "saml-provider-list", "List saml providers", func(cli *aws.SRegion, args *SAMLProviderListOptions) error {
|
||||
samls, err := cli.GetClient().ListSAMLProviders()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(samls, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type SAMLProviderArnOptions struct {
|
||||
ARN string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderArnOptions{}, "saml-provider-show", "Show saml provider", func(cli *aws.SRegion, args *SAMLProviderArnOptions) error {
|
||||
saml, err := cli.GetClient().GetSAMLProvider(args.ARN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(saml)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&SAMLProviderArnOptions{}, "saml-provider-delete", "Delete saml provider", func(cli *aws.SRegion, args *SAMLProviderArnOptions) error {
|
||||
return cli.GetClient().DeleteSAMLProvider(args.ARN)
|
||||
})
|
||||
|
||||
type SAMLProviderCreateOptions struct {
|
||||
NAME string
|
||||
METADATA string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderCreateOptions{}, "saml-provider-create", "Create saml provider", func(cli *aws.SRegion, args *SAMLProviderCreateOptions) error {
|
||||
saml, err := cli.GetClient().CreateSAMLProvider(args.NAME, args.METADATA)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(saml)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SAMLProviderUpdateOptions struct {
|
||||
ARN string
|
||||
METADATA string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderUpdateOptions{}, "saml-provider-update", "Update saml provider", func(cli *aws.SRegion, args *SAMLProviderUpdateOptions) error {
|
||||
saml, err := cli.GetClient().UpdateSAMLProvider(args.ARN, args.METADATA)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(saml)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -297,7 +297,3 @@ func (self *SGoogleProvider) CreateICloudpolicy(opts *cloudprovider.SCloudpolicy
|
||||
func (self *SGoogleProvider) GetSamlEntityId() string {
|
||||
return cloudprovider.SAML_ENTITY_ID_GOOGLE
|
||||
}
|
||||
|
||||
func (self *SGoogleProvider) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return self.client.GetSamlSpInitiatedLoginUrl(idpName)
|
||||
}
|
||||
|
||||
@@ -33,60 +33,62 @@ type Client struct {
|
||||
// 标记初始化状态
|
||||
init bool
|
||||
|
||||
Balances *modules.SBalanceManager
|
||||
Bandwidths *modules.SBandwidthManager
|
||||
Credentials *modules.SCredentialManager
|
||||
Disks *modules.SDiskManager
|
||||
Domains *modules.SDomainManager
|
||||
Eips *modules.SEipManager
|
||||
Elasticcache *modules.SElasticcacheManager
|
||||
DcsAvailableZone *modules.SDcsAvailableZoneManager
|
||||
Flavors *modules.SFlavorManager
|
||||
Images *modules.SImageManager
|
||||
OpenStackImages *modules.SImageManager
|
||||
Interface *modules.SInterfaceManager
|
||||
Jobs *modules.SJobManager
|
||||
Keypairs *modules.SKeypairManager
|
||||
Elb *modules.SLoadbalancerManager
|
||||
ElbBackend *modules.SElbBackendManager
|
||||
ElbBackendGroup *modules.SElbBackendGroupManager
|
||||
ElbListeners *modules.SElbListenersManager
|
||||
ElbCertificates *modules.SElbCertificatesManager
|
||||
ElbHealthCheck *modules.SElbHealthCheckManager
|
||||
ElbL7policies *modules.SElbL7policiesManager
|
||||
ElbPolicies *modules.SElbPoliciesManager
|
||||
ElbWhitelist *modules.SElbWhitelistManager
|
||||
Orders *modules.SOrderManager
|
||||
Port *modules.SPortManager
|
||||
Projects *modules.SProjectManager
|
||||
Regions *modules.SRegionManager
|
||||
SecurityGroupRules *modules.SSecgroupRuleManager
|
||||
SecurityGroups *modules.SSecurityGroupManager
|
||||
NovaSecurityGroups *modules.SSecurityGroupManager
|
||||
Servers *modules.SServerManager
|
||||
ServersV2 *modules.SServerManager
|
||||
NovaServers *modules.SServerManager
|
||||
Snapshots *modules.SSnapshotManager
|
||||
OsSnapshots *modules.SSnapshotManager
|
||||
Subnets *modules.SSubnetManager
|
||||
Users *modules.SUserManager
|
||||
Vpcs *modules.SVpcManager
|
||||
Zones *modules.SZoneManager
|
||||
VpcRoutes *modules.SVpcRouteManager
|
||||
SNatRules *modules.SNatSRuleManager
|
||||
DNatRules *modules.SNatDRuleManager
|
||||
NatGateways *modules.SNatGatewayManager
|
||||
VpcPeerings *modules.SVpcPeeringManager
|
||||
DBInstance *modules.SDBInstanceManager
|
||||
DBInstanceBackup *modules.SDBInstanceBackupManager
|
||||
DBInstanceFlavor *modules.SDBInstanceFlavorManager
|
||||
DBInstanceJob *modules.SDBInstanceJobManager
|
||||
Traces *modules.STraceManager
|
||||
CloudEye *modules.SCloudEyeManager
|
||||
Quotas *modules.SQuotaManager
|
||||
EnterpriseProjects *modules.SEnterpriseProjectManager
|
||||
Roles *modules.SRoleManager
|
||||
Groups *modules.SGroupManager
|
||||
Balances *modules.SBalanceManager
|
||||
Bandwidths *modules.SBandwidthManager
|
||||
Credentials *modules.SCredentialManager
|
||||
Disks *modules.SDiskManager
|
||||
Domains *modules.SDomainManager
|
||||
Eips *modules.SEipManager
|
||||
Elasticcache *modules.SElasticcacheManager
|
||||
DcsAvailableZone *modules.SDcsAvailableZoneManager
|
||||
Flavors *modules.SFlavorManager
|
||||
Images *modules.SImageManager
|
||||
OpenStackImages *modules.SImageManager
|
||||
Interface *modules.SInterfaceManager
|
||||
Jobs *modules.SJobManager
|
||||
Keypairs *modules.SKeypairManager
|
||||
Elb *modules.SLoadbalancerManager
|
||||
ElbBackend *modules.SElbBackendManager
|
||||
ElbBackendGroup *modules.SElbBackendGroupManager
|
||||
ElbListeners *modules.SElbListenersManager
|
||||
ElbCertificates *modules.SElbCertificatesManager
|
||||
ElbHealthCheck *modules.SElbHealthCheckManager
|
||||
ElbL7policies *modules.SElbL7policiesManager
|
||||
ElbPolicies *modules.SElbPoliciesManager
|
||||
ElbWhitelist *modules.SElbWhitelistManager
|
||||
Orders *modules.SOrderManager
|
||||
Port *modules.SPortManager
|
||||
Projects *modules.SProjectManager
|
||||
Regions *modules.SRegionManager
|
||||
SecurityGroupRules *modules.SSecgroupRuleManager
|
||||
SecurityGroups *modules.SSecurityGroupManager
|
||||
NovaSecurityGroups *modules.SSecurityGroupManager
|
||||
Servers *modules.SServerManager
|
||||
ServersV2 *modules.SServerManager
|
||||
NovaServers *modules.SServerManager
|
||||
Snapshots *modules.SSnapshotManager
|
||||
OsSnapshots *modules.SSnapshotManager
|
||||
Subnets *modules.SSubnetManager
|
||||
Users *modules.SUserManager
|
||||
Vpcs *modules.SVpcManager
|
||||
Zones *modules.SZoneManager
|
||||
VpcRoutes *modules.SVpcRouteManager
|
||||
SNatRules *modules.SNatSRuleManager
|
||||
DNatRules *modules.SNatDRuleManager
|
||||
NatGateways *modules.SNatGatewayManager
|
||||
VpcPeerings *modules.SVpcPeeringManager
|
||||
DBInstance *modules.SDBInstanceManager
|
||||
DBInstanceBackup *modules.SDBInstanceBackupManager
|
||||
DBInstanceFlavor *modules.SDBInstanceFlavorManager
|
||||
DBInstanceJob *modules.SDBInstanceJobManager
|
||||
Traces *modules.STraceManager
|
||||
CloudEye *modules.SCloudEyeManager
|
||||
Quotas *modules.SQuotaManager
|
||||
EnterpriseProjects *modules.SEnterpriseProjectManager
|
||||
Roles *modules.SRoleManager
|
||||
Groups *modules.SGroupManager
|
||||
SAMLProviders *modules.SAMLProviderManager
|
||||
SAMLProviderMappings *modules.SAMLProviderMappingManager
|
||||
}
|
||||
|
||||
func (self *Client) SetHttpClient(httpClient *http.Client) {
|
||||
@@ -142,6 +144,8 @@ func (self *Client) SetHttpClient(httpClient *http.Client) {
|
||||
self.EnterpriseProjects.SetHttpClient(httpClient)
|
||||
self.Roles.SetHttpClient(httpClient)
|
||||
self.Groups.SetHttpClient(httpClient)
|
||||
self.SAMLProviders.SetHttpClient(httpClient)
|
||||
self.SAMLProviderMappings.SetHttpClient(httpClient)
|
||||
}
|
||||
|
||||
func (self *Client) InitWithOptions(regionId, domainId, projectId string, credential auth.Credential) error {
|
||||
@@ -229,6 +233,10 @@ func (self *Client) initManagers() {
|
||||
self.Roles.SetDomainId(self.domainId)
|
||||
self.Groups = modules.NewGroupManager(self.signer, self.debug)
|
||||
self.Groups.SetDomainId(self.domainId)
|
||||
self.SAMLProviders = modules.NewSAMLProviderManager(self.signer, self.debug)
|
||||
self.SAMLProviders.SetDomainId(self.domainId)
|
||||
self.SAMLProviderMappings = modules.NewSAMLProviderMappingManager(self.signer, self.debug)
|
||||
self.SAMLProviderMappings.SetDomainId(self.domainId)
|
||||
}
|
||||
|
||||
self.init = true
|
||||
|
||||
@@ -170,6 +170,10 @@ func (self *SResourceManager) GetInContextWithSpec(ctx manager.IManagerContext,
|
||||
request.AddQueryParam(k, v)
|
||||
}
|
||||
|
||||
if len(self.DomainId) > 0 {
|
||||
request.AddHeaderParam("X-Domain-Id", self.DomainId)
|
||||
}
|
||||
|
||||
return self._get(request, responseKey)
|
||||
}
|
||||
|
||||
@@ -216,6 +220,27 @@ func (self *SResourceManager) UpdateInContextWithSpec(ctx manager.IManagerContex
|
||||
return self._do(request, responseKey)
|
||||
}
|
||||
|
||||
func (self *SResourceManager) Patch(id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
return self.PatchInContext(self.ctx, id, params)
|
||||
}
|
||||
|
||||
func (self *SResourceManager) PatchInContext(ctx manager.IManagerContext, id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
return self.PatchInContextWithSpec(ctx, id, "", params, self.Keyword)
|
||||
}
|
||||
|
||||
func (self *SResourceManager) PatchInContextWithSpec(ctx manager.IManagerContext, id string, spec string, params jsonutils.JSONObject, responseKey string) (jsonutils.JSONObject, error) {
|
||||
request := self.newRequest("PATCH", id, spec, ctx)
|
||||
content := getContent(params)
|
||||
if len(content) > 0 {
|
||||
request.SetContent([]byte(content))
|
||||
}
|
||||
if len(self.DomainId) > 0 {
|
||||
request.AddHeaderParam("X-Domain-Id", self.DomainId)
|
||||
}
|
||||
|
||||
return self._do(request, responseKey)
|
||||
}
|
||||
|
||||
func (self *SResourceManager) Delete(id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
return self.DeleteInContext(self.ctx, id, params)
|
||||
}
|
||||
@@ -248,6 +273,9 @@ func (self *SResourceManager) PerformAction(action string, id string, params jso
|
||||
func (self *SResourceManager) PerformAction2(action string, id string, params jsonutils.JSONObject, responseKey string) (jsonutils.JSONObject, error) {
|
||||
request := self.newRequest("POST", id, action, nil)
|
||||
request.SetContent([]byte(getContent(params)))
|
||||
if len(self.DomainId) > 0 {
|
||||
request.AddHeaderParam("X-Domain-Id", self.DomainId)
|
||||
}
|
||||
|
||||
return self._do(request, responseKey)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/auth"
|
||||
)
|
||||
|
||||
type SAMLProviderMappingManager struct {
|
||||
SResourceManager
|
||||
}
|
||||
|
||||
func NewSAMLProviderMappingManager(signer auth.Signer, debug bool) *SAMLProviderMappingManager {
|
||||
return &SAMLProviderMappingManager{SResourceManager: SResourceManager{
|
||||
SBaseManager: NewBaseManager(signer, debug),
|
||||
ServiceName: ServiceNameIAM,
|
||||
Region: "",
|
||||
ProjectId: "",
|
||||
version: "v3/OS-FEDERATION",
|
||||
Keyword: "mapping",
|
||||
KeywordPlural: "mappings",
|
||||
|
||||
ResourceKeyword: "mappings",
|
||||
}}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/auth"
|
||||
)
|
||||
|
||||
type SAMLProviderManager struct {
|
||||
SResourceManager
|
||||
}
|
||||
|
||||
func NewSAMLProviderManager(signer auth.Signer, debug bool) *SAMLProviderManager {
|
||||
return &SAMLProviderManager{SResourceManager: SResourceManager{
|
||||
SBaseManager: NewBaseManager(signer, debug),
|
||||
ServiceName: ServiceNameIAM,
|
||||
Region: "",
|
||||
ProjectId: "",
|
||||
version: "v3/OS-FEDERATION",
|
||||
Keyword: "identity_provider",
|
||||
KeywordPlural: "identity_providers",
|
||||
|
||||
ResourceKeyword: "identity_providers",
|
||||
}}
|
||||
}
|
||||
@@ -560,7 +560,3 @@ func (self *SHuaweiClient) initOwner() error {
|
||||
self.ownerId = ownerId
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return fmt.Sprintf("https://auth.huaweicloud.com/authui/federation/websso?domain_id=%s&idp=%s&protocol=saml", self.ownerId, idpName)
|
||||
}
|
||||
|
||||
@@ -289,6 +289,14 @@ func (self *SHuaweiProvider) GetSamlEntityId() string {
|
||||
return cloudprovider.SAML_ENTITY_ID_HUAWEI_CLOUD
|
||||
}
|
||||
|
||||
func (self *SHuaweiProvider) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return self.client.GetSamlSpInitiatedLoginUrl(idpName)
|
||||
func (self *SHuaweiProvider) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) {
|
||||
return self.client.GetICloudSAMLProviders()
|
||||
}
|
||||
|
||||
func (self *SHuaweiProvider) CreateICloudSAMLProvider(opts *cloudprovider.SAMLProviderCreateOptions) (cloudprovider.ICloudSAMLProvider, error) {
|
||||
sp, err := self.client.CreateSAMLProvider(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateSAMLProvider")
|
||||
}
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package huawei
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
)
|
||||
|
||||
type SAMLProviderLinks struct {
|
||||
Self string
|
||||
Protocols string
|
||||
}
|
||||
|
||||
type SAMLProvider struct {
|
||||
multicloud.SResourceBase
|
||||
client *SHuaweiClient
|
||||
|
||||
Id string
|
||||
Links SAMLProviderLinks
|
||||
Description string
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetId() string {
|
||||
return self.Id
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetGlobalId() string {
|
||||
return self.Id
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetName() string {
|
||||
return self.Id
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetStatus() string {
|
||||
mappings, err := self.client.ListSAMLProviderMappings()
|
||||
if err != nil {
|
||||
return api.SAML_PROVIDER_STATUS_UNKNOWN
|
||||
}
|
||||
for i := range mappings {
|
||||
if mappings[i].Id == DEFAULT_ONECLOUD_MAPPING {
|
||||
return api.SAML_PROVIDER_STATUS_AVAILABLE
|
||||
}
|
||||
}
|
||||
return api.SAML_PROVIDER_STATUS_UNVALIABLE
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetAuthUrl() string {
|
||||
return fmt.Sprintf("https://auth.huaweicloud.com/authui/federation/websso?domain_id=%s&idp=%s&protocol=saml", self.client.ownerId, self.Id)
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) Delete() error {
|
||||
return self.client.DeleteSAMLProvider(self.Id)
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetMetadataDocument() (*samlutils.EntityDescriptor, error) {
|
||||
info, err := self.client.GetSAMLProviderMetadata(self.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProviderMetadata(%s)", self.Id)
|
||||
}
|
||||
metadata, err := samlutils.ParseMetadata([]byte(info.Data))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ParseMetadata")
|
||||
}
|
||||
return &metadata, nil
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) ListSAMLProviders() ([]SAMLProvider, error) {
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "newGeneralAPIClient")
|
||||
}
|
||||
samls := []SAMLProvider{}
|
||||
err = doListAllWithNextLink(client.SAMLProviders.List, nil, &samls)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "doListAll")
|
||||
}
|
||||
return samls, nil
|
||||
}
|
||||
|
||||
type SAMLProviderProtocol struct {
|
||||
MappingId string
|
||||
Id string
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) GetSAMLProviderProtocols(id string) ([]SAMLProviderProtocol, error) {
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newGeneralAPIClient")
|
||||
}
|
||||
resp, err := client.SAMLProviders.ListInContextWithSpec(nil, fmt.Sprintf("%s/protocols", id), nil, "protocols")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListInContextWithSpec")
|
||||
}
|
||||
protocols := []SAMLProviderProtocol{}
|
||||
return protocols, jsonutils.Update(&protocols, resp.Data)
|
||||
}
|
||||
|
||||
type SAMLProviderMetadata struct {
|
||||
DomainId string
|
||||
UpdateTime time.Time
|
||||
Data string
|
||||
IdpId string
|
||||
ProtocolId string
|
||||
Id string
|
||||
EntityId string
|
||||
XaccountType string
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) GetSAMLProviderMetadata(id string) (*SAMLProviderMetadata, error) {
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newGeneralAPIClient")
|
||||
}
|
||||
client.SAMLProviders.SetVersion("v3-ext/OS-FEDERATION")
|
||||
resp, err := client.SAMLProviders.GetInContextWithSpec(nil, id, fmt.Sprintf("protocols/saml/metadata"), nil, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metadata := &SAMLProviderMetadata{}
|
||||
err = resp.Unmarshal(metadata)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "resp.Unmarshal")
|
||||
}
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) UpdateSAMLProviderMetadata(id, metadata string) error {
|
||||
params := map[string]string{
|
||||
"domain_id": self.ownerId,
|
||||
"xaccount_type": "",
|
||||
"metadata": metadata,
|
||||
}
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "newGeneralAPIClient")
|
||||
}
|
||||
client.SAMLProviders.SetVersion("v3-ext/OS-FEDERATION")
|
||||
_, err = client.SAMLProviders.PerformAction2("protocols/saml/metadata", id, jsonutils.Marshal(params), "")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SAMLProvider.PerformAction")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) {
|
||||
samls, err := self.ListSAMLProviders()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListSAMLProviders")
|
||||
}
|
||||
ret := []cloudprovider.ICloudSAMLProvider{}
|
||||
for i := range samls {
|
||||
samls[i].client = self
|
||||
ret = append(ret, &samls[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) DeleteSAMLProvider(id string) error {
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "newGeneralAPIClient")
|
||||
}
|
||||
_, err = client.SAMLProviders.Delete(id, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) CreateSAMLProvider(opts *cloudprovider.SAMLProviderCreateOptions) (*SAMLProvider, error) {
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newGeneralAPIClient")
|
||||
}
|
||||
params := jsonutils.Marshal(map[string]interface{}{
|
||||
"identity_provider": map[string]interface{}{
|
||||
"description": opts.Name,
|
||||
"enabled": true,
|
||||
},
|
||||
})
|
||||
name := []byte{}
|
||||
for _, c := range opts.Name {
|
||||
if unicode.IsLetter(c) || unicode.IsNumber(c) || c == '-' || c == '_' {
|
||||
name = append(name, byte(c))
|
||||
} else {
|
||||
name = append(name, '-')
|
||||
}
|
||||
}
|
||||
opts.Name = string(name)
|
||||
_, err = client.SAMLProviders.Update(opts.Name, params)
|
||||
if err != nil {
|
||||
if he, ok := err.(*modules.HuaweiClientError); ok && he.Code != 409 {
|
||||
return nil, errors.Wrapf(err, "SAMLProviders.Update")
|
||||
}
|
||||
}
|
||||
ret := SAMLProvider{client: self, Id: opts.Name}
|
||||
err = self.UpdateSAMLProviderMetadata(opts.Name, opts.Metadata.String())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
err = self.InitSAMLProviderMapping(opts.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "InitSAMLProviderMapping")
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
|
||||
type SAMLProviderMapping struct {
|
||||
Id string
|
||||
Rules jsonutils.JSONObject
|
||||
}
|
||||
|
||||
const (
|
||||
DEFAULT_ONECLOUD_MAPPING = "yunion-onecloud-mapping"
|
||||
)
|
||||
|
||||
var (
|
||||
onecloudMappingRules = jsonutils.Marshal(map[string]interface{}{
|
||||
"rules": []map[string]interface{}{
|
||||
{
|
||||
"remote": []map[string]interface{}{
|
||||
{
|
||||
"type": "User",
|
||||
},
|
||||
{
|
||||
"type": "Groups",
|
||||
},
|
||||
},
|
||||
"local": []map[string]interface{}{
|
||||
{
|
||||
"groups": "{1}",
|
||||
"user": map[string]string{"name": "{0}"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
func (self *SHuaweiClient) ListSAMLProviderMappings() ([]SAMLProviderMapping, error) {
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newGeneralAPIClient")
|
||||
}
|
||||
mappings := []SAMLProviderMapping{}
|
||||
err = doListAllWithNextLink(client.SAMLProviderMappings.List, nil, &mappings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mappings, nil
|
||||
}
|
||||
|
||||
func (self *SHuaweiClient) InitSAMLProviderMapping(spId string) error {
|
||||
client, err := self.newGeneralAPIClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "newGeneralAPIClient")
|
||||
}
|
||||
|
||||
mappings, err := self.ListSAMLProviderMappings()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ListSAMLProviderMappings")
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"mapping": onecloudMappingRules,
|
||||
}
|
||||
|
||||
find := false
|
||||
for i := range mappings {
|
||||
if mappings[i].Id == DEFAULT_ONECLOUD_MAPPING {
|
||||
find = true
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
_, err = client.SAMLProviderMappings.Update(DEFAULT_ONECLOUD_MAPPING, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create mapping")
|
||||
}
|
||||
}
|
||||
protocols, err := self.GetSAMLProviderProtocols(spId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetSAMLProviderProtocols")
|
||||
}
|
||||
params = map[string]interface{}{
|
||||
"protocol": map[string]string{
|
||||
"mapping_id": DEFAULT_ONECLOUD_MAPPING,
|
||||
},
|
||||
}
|
||||
for i := range protocols {
|
||||
if protocols[i].Id == "saml" {
|
||||
if protocols[i].MappingId == DEFAULT_ONECLOUD_MAPPING {
|
||||
return nil
|
||||
}
|
||||
_, err = client.SAMLProviders.PatchInContextWithSpec(nil, spId, "protocols/saml", jsonutils.Marshal(params), "")
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = client.SAMLProviders.UpdateInContextWithSpec(nil, spId, "protocols/saml", jsonutils.Marshal(params), "")
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/huawei"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SAMLProviderListOptions struct {
|
||||
}
|
||||
shellutils.R(&SAMLProviderListOptions{}, "saml-provider-list", "List saml provider", func(cli *huawei.SRegion, args *SAMLProviderListOptions) error {
|
||||
result, err := cli.GetClient().ListSAMLProviders()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SAMLProviderIdOptions struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderIdOptions{}, "saml-provider-delete", "Delete saml provider", func(cli *huawei.SRegion, args *SAMLProviderIdOptions) error {
|
||||
return cli.GetClient().DeleteSAMLProvider(args.ID)
|
||||
})
|
||||
|
||||
shellutils.R(&SAMLProviderIdOptions{}, "saml-provider-protocol-list", "List saml provider protocol", func(cli *huawei.SRegion, args *SAMLProviderIdOptions) error {
|
||||
result, err := cli.GetClient().GetSAMLProviderProtocols(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&SAMLProviderIdOptions{}, "saml-provider-metadata-show", "Show saml provider metadata", func(cli *huawei.SRegion, args *SAMLProviderIdOptions) error {
|
||||
result, err := cli.GetClient().GetSAMLProviderMetadata(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SAMLProviderMetadataOptions struct {
|
||||
ID string
|
||||
METADATA string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderMetadataOptions{}, "saml-provider-metadata-update", "Update saml provider metadata", func(cli *huawei.SRegion, args *SAMLProviderMetadataOptions) error {
|
||||
return cli.GetClient().UpdateSAMLProviderMetadata(args.ID, args.METADATA)
|
||||
})
|
||||
|
||||
type MappingListOptions struct {
|
||||
}
|
||||
|
||||
shellutils.R(&MappingListOptions{}, "saml-provider-mapping-list", "List saml provider mapping", func(cli *huawei.SRegion, args *MappingListOptions) error {
|
||||
mappings, err := cli.GetClient().ListSAMLProviderMappings()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(mappings, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MappingInitOptions struct {
|
||||
SAML_PROVIDER string
|
||||
}
|
||||
|
||||
shellutils.R(&MappingInitOptions{}, "saml-provider-mapping-init", "Init saml provider mapping", func(cli *huawei.SRegion, args *MappingInitOptions) error {
|
||||
return cli.GetClient().InitSAMLProviderMapping(args.SAML_PROVIDER)
|
||||
})
|
||||
|
||||
}
|
||||
@@ -16,9 +16,15 @@ package qcloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -37,7 +43,18 @@ const (
|
||||
"UpdateTime": "2020-08-11 17:03:30"
|
||||
*/
|
||||
|
||||
type SPrincipal struct {
|
||||
Federated []string
|
||||
}
|
||||
|
||||
type Statement struct {
|
||||
Action string
|
||||
Effect string
|
||||
Principal SPrincipal
|
||||
}
|
||||
|
||||
type SRole struct {
|
||||
multicloud.SResourceBase
|
||||
client *SQcloudClient
|
||||
|
||||
AddTime time.Time
|
||||
@@ -51,6 +68,92 @@ type SRole struct {
|
||||
UpdateTime time.Time
|
||||
}
|
||||
|
||||
func (self *SRole) GetGlobalId() string {
|
||||
return self.RoleName
|
||||
}
|
||||
|
||||
func (self *SRole) GetName() string {
|
||||
return self.RoleName
|
||||
}
|
||||
|
||||
func (self *SRole) GetDocument() *jsonutils.JSONDict {
|
||||
if len(self.PolicyDocument) > 0 {
|
||||
document, err := jsonutils.Parse([]byte(self.PolicyDocument))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return document.(*jsonutils.JSONDict)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRole) GetSAMLProvider() string {
|
||||
document := self.GetDocument()
|
||||
if document != nil {
|
||||
statements := []Statement{}
|
||||
document.Unmarshal(&statements, "statement")
|
||||
for i := range statements {
|
||||
if statements[i].Action == "name/sts:AssumeRoleWithSAML" {
|
||||
for _, federated := range statements[i].Principal.Federated {
|
||||
if strings.Contains(federated, ":saml-provider/") {
|
||||
info := strings.Split(federated, "/")
|
||||
return info[len(info)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SRole) Delete() error {
|
||||
return self.client.DeleteRole(self.RoleName)
|
||||
}
|
||||
|
||||
func (self *SRole) GetICloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
|
||||
ret := []cloudprovider.ICloudpolicy{}
|
||||
for {
|
||||
part, total, err := self.client.ListAttachedRolePolicies(self.RoleName, "", len(ret), 50)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListAttachedRolePolicies")
|
||||
}
|
||||
for i := range part {
|
||||
part[i].client = self.client
|
||||
ret = append(ret, &part[i])
|
||||
}
|
||||
if len(ret) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRole) AttachPolicy(id string) error {
|
||||
return self.client.AttachRolePolicy(self.RoleName, id)
|
||||
}
|
||||
|
||||
func (self *SRole) DetachPolicy(id string) error {
|
||||
return self.client.DetachRolePolicy(self.RoleName, id)
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) GetICloudroles() ([]cloudprovider.ICloudrole, error) {
|
||||
ret := []cloudprovider.ICloudrole{}
|
||||
for {
|
||||
part, total, err := self.DescribeRoleList(len(ret), 200)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeRoleList")
|
||||
}
|
||||
for i := range part {
|
||||
part[i].client = self
|
||||
ret = append(ret, &part[i])
|
||||
}
|
||||
if len(ret) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) DescribeRoleList(offset int, limit int) ([]SRole, int, error) {
|
||||
if limit < 1 || limit > 200 {
|
||||
limit = 200
|
||||
@@ -76,6 +179,9 @@ func (self *SQcloudClient) DescribeRoleList(offset int, limit int) ([]SRole, int
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) CreateRole(name, document, desc string) (*SRole, error) {
|
||||
if len(document) == 0 {
|
||||
document = DEFAULT_ROLE_DOCUMENT
|
||||
}
|
||||
params := map[string]string{
|
||||
"RoleName": name,
|
||||
"PolicyDocument": document,
|
||||
@@ -145,7 +251,11 @@ func (self *SQcloudClient) DeleteRole(name string) error {
|
||||
func (self *SQcloudClient) AttachRolePolicy(roleName string, policyId string) error {
|
||||
params := map[string]string{
|
||||
"AttachRoleName": roleName,
|
||||
"PolicyId": policyId,
|
||||
}
|
||||
if _id, _ := strconv.Atoi(policyId); _id > 0 {
|
||||
params["PolicyId"] = policyId
|
||||
} else {
|
||||
params["PolicyName"] = policyId
|
||||
}
|
||||
_, err := self.camRequest("AttachRolePolicy", params)
|
||||
return err
|
||||
@@ -154,7 +264,11 @@ func (self *SQcloudClient) AttachRolePolicy(roleName string, policyId string) er
|
||||
func (self *SQcloudClient) DetachRolePolicy(roleName string, policyId string) error {
|
||||
params := map[string]string{
|
||||
"DetachRoleName": roleName,
|
||||
"PolicyId": policyId,
|
||||
}
|
||||
if _id, _ := strconv.Atoi(policyId); _id > 0 {
|
||||
params["PolicyId"] = policyId
|
||||
} else {
|
||||
params["PolicyName"] = policyId
|
||||
}
|
||||
_, err := self.camRequest("DetachRolePolicy", params)
|
||||
return err
|
||||
|
||||
@@ -55,7 +55,7 @@ func (user *SUser) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, erro
|
||||
}
|
||||
ret := []cloudprovider.ICloudpolicy{}
|
||||
for i := range policies {
|
||||
if policies[i].PolicyType == "QCS" {
|
||||
if policies[i].PolicyType == "QCS" || policies[i].PolicyType == "" {
|
||||
policies[i].client = user.client
|
||||
ret = append(ret, &policies[i])
|
||||
}
|
||||
@@ -79,7 +79,7 @@ func (user *SUser) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, erro
|
||||
}
|
||||
ret := []cloudprovider.ICloudpolicy{}
|
||||
for i := range policies {
|
||||
if policies[i].PolicyType != "QCS" {
|
||||
if policies[i].PolicyType == "User" {
|
||||
policies[i].client = user.client
|
||||
ret = append(ret, &policies[i])
|
||||
}
|
||||
|
||||
@@ -370,16 +370,58 @@ func (self *SQcloudProvider) GetSamlEntityId() string {
|
||||
return cloudprovider.SAML_ENTITY_ID_QCLOUD
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return self.client.GetSamlSpInitiatedLoginUrl(idpName)
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) GetICloudDnsZones() ([]cloudprovider.ICloudDnsZone, error) {
|
||||
return self.client.GetICloudDnsZones()
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) GetICloudDnsZoneById(id string) (cloudprovider.ICloudDnsZone, error) {
|
||||
return self.client.GetDomainById(id)
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) CreateICloudDnsZone(opts *cloudprovider.SDnsZoneCreateOptions) (cloudprovider.ICloudDnsZone, error) {
|
||||
return self.client.CreateICloudDnsZone(opts)
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) CreateICloudSAMLProvider(opts *cloudprovider.SAMLProviderCreateOptions) (cloudprovider.ICloudSAMLProvider, error) {
|
||||
saml, err := self.client.CreateSAMLProvider(opts.Name, opts.Metadata.String(), "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CreateSAMLProvider")
|
||||
}
|
||||
return saml, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) {
|
||||
return self.client.GetICloudSAMLProviders()
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) CreateICloudrole(opts *cloudprovider.SRoleCreateOptions) (cloudprovider.ICloudrole, error) {
|
||||
if len(opts.SAMLProvider) > 0 {
|
||||
document := fmt.Sprintf(`{"version":"2.0","statement":[{"action":"name/sts:AssumeRoleWithSAML","effect":"allow","principal":{"federated":["qcs::cam::uin/%s:saml-provider/%s"]},"condition":{}}]}`, self.client.GetAccountId(), opts.SAMLProvider)
|
||||
role, err := self.client.CreateRole(opts.Name, document, opts.Desc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateRole")
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
role, err := self.client.CreateRole(opts.Name, "", opts.Desc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "")
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) GetICloudroles() ([]cloudprovider.ICloudrole, error) {
|
||||
return self.client.GetICloudroles()
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) GetICloudroleByName(name string) (cloudprovider.ICloudrole, error) {
|
||||
role, err := self.client.GetRole(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetRole(%s)", name)
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudProvider) GetICloudroleById(id string) (cloudprovider.ICloudrole, error) {
|
||||
return self.GetICloudroleByName(id)
|
||||
}
|
||||
|
||||
@@ -955,7 +955,3 @@ func (self *SQcloudClient) GetCapabilities() []string {
|
||||
}
|
||||
return caps
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) GetSamlSpInitiatedLoginUrl(idpName string) string {
|
||||
return fmt.Sprintf("https://cloud.tencent.com/login/forwardIdp/%s/%s", self.ownerName, idpName)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package qcloud
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/util/samlutils"
|
||||
)
|
||||
|
||||
type SAMLProvider struct {
|
||||
multicloud.SResourceBase
|
||||
client *SQcloudClient
|
||||
|
||||
Name string
|
||||
Description string
|
||||
CreateTime time.Time
|
||||
ModifyTime time.Time
|
||||
SAMLMetadata string
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetId() string {
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetGlobalId() string {
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetName() string {
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetStatus() string {
|
||||
return api.SAML_PROVIDER_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) Delete() error {
|
||||
return self.client.DeleteSAMLProvider(self.Name)
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetAuthUrl() string {
|
||||
return fmt.Sprintf("https://cloud.tencent.com/login/forwardIdp/%s/%s", self.client.ownerName, self.Name)
|
||||
}
|
||||
|
||||
func (self *SAMLProvider) GetMetadataDocument() (*samlutils.EntityDescriptor, error) {
|
||||
provider, err := self.client.GetSAMLProvider(self.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProvider(%s)", self.Name)
|
||||
}
|
||||
metadata, err := base64.StdEncoding.DecodeString(provider.SAMLMetadata)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "decode metadata")
|
||||
}
|
||||
ret, err := samlutils.ParseMetadata(metadata)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ParseMetadata")
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) ListSAMLProviders() ([]SAMLProvider, error) {
|
||||
resp, err := self.camRequest("ListSAMLProviders", nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListSAMLProviders")
|
||||
}
|
||||
result := []SAMLProvider{}
|
||||
err = resp.Unmarshal(&result, "SAMLProviderSet")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Unmarshal")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) CreateSAMLProvider(name, metadata, desc string) (*SAMLProvider, error) {
|
||||
if len(desc) == 0 {
|
||||
desc = "For CloudId Service"
|
||||
}
|
||||
//支持3-128个数字、大小写字母、和+=,.@_-
|
||||
name = func() string {
|
||||
ret := ""
|
||||
for _, c := range name {
|
||||
if unicode.IsLetter(c) || unicode.IsNumber(c) ||
|
||||
c == '+' || c == '=' || c == ',' || c == '.' || c == '@' || c == '_' || c == '-' {
|
||||
ret += string(c)
|
||||
} else {
|
||||
ret += "-"
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}()
|
||||
if len(name) > 128 {
|
||||
name = name[:128]
|
||||
}
|
||||
params := map[string]string{
|
||||
"Name": name,
|
||||
"Description": desc,
|
||||
"SAMLMetadataDocument": base64.StdEncoding.EncodeToString([]byte(metadata)),
|
||||
}
|
||||
_, err := self.camRequest("CreateSAMLProvider", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateSAMLProvider")
|
||||
}
|
||||
return self.GetSAMLProvider(name)
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) GetSAMLProvider(name string) (*SAMLProvider, error) {
|
||||
params := map[string]string{
|
||||
"Name": name,
|
||||
}
|
||||
resp, err := self.camRequest("GetSAMLProvider", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProvider")
|
||||
}
|
||||
result := &SAMLProvider{client: self}
|
||||
err = resp.Unmarshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) DeleteSAMLProvider(name string) error {
|
||||
params := map[string]string{
|
||||
"Name": name,
|
||||
}
|
||||
_, err := self.camRequest("DeleteSAMLProvider", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) UpdateSAMLProvider(name, metadata, desc string) error {
|
||||
params := map[string]string{
|
||||
"Name": name,
|
||||
}
|
||||
if len(desc) > 0 {
|
||||
params["Description"] = desc
|
||||
}
|
||||
if len(metadata) > 0 {
|
||||
params["SAMLMetadataDocument"] = base64.StdEncoding.EncodeToString([]byte(metadata))
|
||||
}
|
||||
_, err := self.camRequest("UpdateSAMLProvider", params)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "UpdateSAMLProvider")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SQcloudClient) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) {
|
||||
providers, err := self.ListSAMLProviders()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListSAMLProviders")
|
||||
}
|
||||
ret := []cloudprovider.ICloudSAMLProvider{}
|
||||
for i := range providers {
|
||||
providers[i].client = self
|
||||
ret = append(ret, &providers[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SAMLProviderListOptions struct {
|
||||
}
|
||||
shellutils.R(&SAMLProviderListOptions{}, "saml-provider-list", "List saml provider", func(cli *qcloud.SRegion, args *SAMLProviderListOptions) error {
|
||||
result, err := cli.GetClient().ListSAMLProviders()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SAMLProviderCreateOptions struct {
|
||||
NAME string
|
||||
Desc string
|
||||
METADATA string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderCreateOptions{}, "saml-provider-create", "Create saml provider", func(cli *qcloud.SRegion, args *SAMLProviderCreateOptions) error {
|
||||
result, err := cli.GetClient().CreateSAMLProvider(args.NAME, args.METADATA, args.Desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SAMLProviderNameOptions struct {
|
||||
NAME string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderNameOptions{}, "saml-provider-show", "Show saml provider", func(cli *qcloud.SRegion, args *SAMLProviderNameOptions) error {
|
||||
result, err := cli.GetClient().GetSAMLProvider(args.NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&SAMLProviderNameOptions{}, "saml-provider-delete", "Delete saml provider", func(cli *qcloud.SRegion, args *SAMLProviderNameOptions) error {
|
||||
return cli.GetClient().DeleteSAMLProvider(args.NAME)
|
||||
})
|
||||
|
||||
type SAMLProviderUpdateOptions struct {
|
||||
NAME string
|
||||
Desc string
|
||||
Metadata string
|
||||
}
|
||||
|
||||
shellutils.R(&SAMLProviderUpdateOptions{}, "saml-provider-update", "Update saml provider", func(cli *qcloud.SRegion, args *SAMLProviderUpdateOptions) error {
|
||||
return cli.GetClient().UpdateSAMLProvider(args.NAME, args.Metadata, args.Desc)
|
||||
})
|
||||
|
||||
}
|
||||
@@ -83,7 +83,11 @@ func (idp *SSAMLIdpInstance) AddHandlers(app *appsrv.Application, prefix string,
|
||||
handler = middleware(handler)
|
||||
}
|
||||
app.AddHandler("GET", idp.redirectLogoutPath, handler)
|
||||
app.AddHandler("GET", idp.idpInitiatedSSOPath, idp.idpInitiatedSSOHandler)
|
||||
handler = idp.idpInitiatedSSOHandler
|
||||
if middleware != nil {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
app.AddHandler("GET", idp.idpInitiatedSSOPath, handler)
|
||||
|
||||
log.Infof("IDP metadata: %s", idp.getMetadataUrl(IDP_ID_KEY))
|
||||
log.Infof("IDP redirect login: %s", idp.getRedirectLoginUrl(IDP_ID_KEY))
|
||||
@@ -141,7 +145,7 @@ func (idp *SSAMLIdpInstance) getIdpInitiatedSSOUrl() string {
|
||||
func (idp *SSAMLIdpInstance) metadataHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
params := appctx.AppContextParams(ctx)
|
||||
idpId := params[IDP_ID_KEY]
|
||||
desc := idp.getMetadata(idpId)
|
||||
desc := idp.GetMetadata(idpId)
|
||||
appsrv.SendXmlWithIndent(w, nil, desc, true)
|
||||
}
|
||||
|
||||
@@ -187,7 +191,7 @@ func (idp *SSAMLIdpInstance) idpInitiatedSSOHandler(ctx context.Context, w http.
|
||||
appsrv.SendHTML(w, respHtml)
|
||||
}
|
||||
|
||||
func (idp *SSAMLIdpInstance) getMetadata(idpId string) samlutils.EntityDescriptor {
|
||||
func (idp *SSAMLIdpInstance) GetMetadata(idpId string) samlutils.EntityDescriptor {
|
||||
input := samlutils.SSAMLIdpMetadataInput{
|
||||
EntityId: idp.saml.GetEntityId(),
|
||||
CertString: idp.saml.GetCertString(),
|
||||
|
||||
@@ -37,7 +37,7 @@ func NewSAMLIdp(entityId, redirectSsoUrl string) *SSAMLIdentityProvider {
|
||||
|
||||
func NewSAMLIdpFromDescriptor(desc samlutils.EntityDescriptor) (*SSAMLIdentityProvider, error) {
|
||||
entityId := desc.EntityId
|
||||
if desc.IDPSSODescriptor != nil {
|
||||
if desc.IDPSSODescriptor == nil {
|
||||
return nil, errors.Wrap(httperrors.ErrInputParameter, "missing IDPSSODescriptor")
|
||||
}
|
||||
redirectSsoUrl := findSSOUrl(desc, samlutils.BINDING_HTTP_REDIRECT)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user