mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-30 17:13:08 +08:00
fix: client auth needs project domain info
This commit is contained in:
+4
-1
@@ -52,7 +52,9 @@ type BaseOptions struct {
|
||||
OsUsername string `default:"$OS_USERNAME" help:"Username, defaults to env[OS_USERNAME]"`
|
||||
OsPassword string `default:"$OS_PASSWORD" help:"Password, defaults to env[OS_PASSWORD]"`
|
||||
// OsProjectId string `default:"$OS_PROJECT_ID" help:"Proejct ID, defaults to env[OS_PROJECT_ID]"`
|
||||
OsProjectName string `default:"$OS_PROJECT_NAME" help:"Project name, defaults to env[OS_PROJECT_NAME]"`
|
||||
OsProjectName string `default:"$OS_PROJECT_NAME" help:"Project name, defaults to env[OS_PROJECT_NAME]"`
|
||||
OsProjectDomain string `default:"$OS_PROJECT_DOMAIN" help:"Domain name of project, defaults to env[OS_PROJECT_DOMAIN]"`
|
||||
|
||||
OsDomainName string `default:"$OS_DOMAIN_NAME" help:"Domain name, defaults to env[OS_DOMAIN_NAME]"`
|
||||
OsAuthURL string `default:"$OS_AUTH_URL" help:"Defaults to env[OS_AUTH_URL]"`
|
||||
OsRegionName string `default:"$OS_REGION_NAME" help:"Defaults to env[OS_REGION_NAME]"`
|
||||
@@ -178,6 +180,7 @@ func newClientSession(options *BaseOptions) (*mcclient.ClientSession, error) {
|
||||
options.OsPassword,
|
||||
options.OsDomainName,
|
||||
options.OsProjectName,
|
||||
options.OsProjectDomain,
|
||||
mcclient.AuthSourceCli)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+12
-11
@@ -27,16 +27,17 @@ import (
|
||||
)
|
||||
|
||||
type BaseOptions struct {
|
||||
Debug bool `help:"debug mode"`
|
||||
Help bool `help:"Show help"`
|
||||
AuthURL string `help:"Auth URL" default:"$OPENSTACK_AUTH_URL"`
|
||||
Username string `help:"Username" default:"$OPENSTACK_USERNAME"`
|
||||
Password string `help:"Password" default:"$OPENSTACK_PASSWORD"`
|
||||
Project string `help:"Project" default:"$OPENSTACK_PROJECT"`
|
||||
EndpointType string `help:"Project" default:"$OPENSTACK_ENDPOINT_TYPE|internal"`
|
||||
DomainName string `help:"DomainName" default:"$OPENSTACK_DOMAIN_NAME"`
|
||||
RegionID string `help:"RegionId" default:"$OPENSTACK_REGION_ID"`
|
||||
SUBCOMMAND string `help:"openstackcli subcommand" subcommand:"true"`
|
||||
Debug bool `help:"debug mode"`
|
||||
Help bool `help:"Show help"`
|
||||
AuthURL string `help:"Auth URL" default:"$OPENSTACK_AUTH_URL"`
|
||||
Username string `help:"Username" default:"$OPENSTACK_USERNAME"`
|
||||
Password string `help:"Password" default:"$OPENSTACK_PASSWORD"`
|
||||
Project string `help:"Project" default:"$OPENSTACK_PROJECT"`
|
||||
EndpointType string `help:"Project" default:"$OPENSTACK_ENDPOINT_TYPE|internal"`
|
||||
DomainName string `help:"Domain of user" default:"$OPENSTACK_DOMAIN_NAME"`
|
||||
ProjectDomain string `help:"Domain of project" default:"$OPENSTACK_PROJECT_DOMAIN"`
|
||||
RegionID string `help:"RegionId" default:"$OPENSTACK_REGION_ID"`
|
||||
SUBCOMMAND string `help:"openstackcli subcommand" subcommand:"true"`
|
||||
}
|
||||
|
||||
func getSubcommandParser() (*structarg.ArgumentParser, error) {
|
||||
@@ -92,7 +93,7 @@ func newClient(options *BaseOptions) (*openstack.SRegion, error) {
|
||||
return nil, fmt.Errorf("Missing Password")
|
||||
}
|
||||
|
||||
cli, err := openstack.NewOpenStackClient("", "", options.AuthURL, options.Username, options.Password, options.Project, options.EndpointType, options.DomainName, options.Debug)
|
||||
cli, err := openstack.NewOpenStackClient("", "", options.AuthURL, options.Username, options.Password, options.Project, options.EndpointType, options.DomainName, options.ProjectDomain, options.Debug)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -48,11 +48,14 @@ func InitAuth(options *common_options.CommonOptions, authComplete auth.AuthCompl
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
a := auth.NewAuthInfo(options.AuthURL,
|
||||
a := auth.NewAuthInfo(
|
||||
options.AuthURL,
|
||||
options.AdminDomain,
|
||||
options.AdminUser,
|
||||
options.AdminPassword,
|
||||
options.AdminProject)
|
||||
options.AdminProject,
|
||||
options.AdminProjectDomain,
|
||||
)
|
||||
|
||||
// debug := options.LogLevel == "debug"
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ type CommonOptions struct {
|
||||
AdminDomain string `help:"Admin user domain"`
|
||||
AdminPassword string `help:"Admin password" alias:"admin-passwd"`
|
||||
AdminProject string `help:"Admin project" default:"system" alias:"admin-tenant-name"`
|
||||
AdminProjectDomain string `help:"Domain of Admin project"`
|
||||
AuthTokenCacheSize uint32 `help:"Auth token Cache Size" default:"2048"`
|
||||
|
||||
BaseOptions
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@ func (r *SRegionDNS) getAdminSession(ctx context.Context) *mcclient.ClientSessio
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) initAuth() {
|
||||
authInfo := auth.NewAuthInfo(r.AuthUrl, "", r.AdminUser, r.AdminPassword, r.AdminProject)
|
||||
authInfo := auth.NewAuthInfo(r.AuthUrl, "", r.AdminUser, r.AdminPassword, r.AdminProject, "")
|
||||
auth.Init(authInfo, false, true, "", "")
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ func (manager *SDomainManager) FetchDomainById(domainId string) (*SDomain, error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := manager.Query().Equals("id", domainId).NotEquals("id", api.KeystoneDomainRoot)
|
||||
q := manager.Query().Equals("id", domainId)
|
||||
err = q.First(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -269,6 +269,7 @@ func (manager *SIdentityProviderManager) ValidateCreateData(ctx context.Context,
|
||||
return nil, httperrors.NewInputParameterError("invalid template")
|
||||
}
|
||||
drvName = api.IdpTemplateDriver[template]
|
||||
data.Set("driver", jsonutils.NewString(drvName))
|
||||
} else {
|
||||
drvName, _ = data.GetString("driver")
|
||||
if len(drvName) == 0 {
|
||||
|
||||
@@ -126,18 +126,36 @@ func (manager *SProjectManager) Query(fields ...string) *sqlchemy.SQuery {
|
||||
func (manager *SProjectManager) FetchProjectByName(projectName string, domainId, domainName string) (*SProject, error) {
|
||||
obj, err := db.NewModelObject(manager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "db.NewModelObject")
|
||||
}
|
||||
domain, err := DomainManager.FetchDomain(domainId, domainName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(domainId) == 0 && len(domainName) == 0 {
|
||||
q := manager.Query().Equals("name", projectName)
|
||||
cnt, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CountWithError")
|
||||
}
|
||||
if cnt == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
if cnt > 1 {
|
||||
return nil, sqlchemy.ErrDuplicateEntry
|
||||
}
|
||||
err = q.First(obj)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "q.First")
|
||||
}
|
||||
} else {
|
||||
domain, err := DomainManager.FetchDomain(domainId, domainName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "DomainManager.FetchDomain")
|
||||
}
|
||||
q := manager.Query().Equals("name", projectName).Equals("domain_id", domain.Id)
|
||||
err = q.First(obj)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "q.First")
|
||||
}
|
||||
}
|
||||
q := manager.Query().Equals("name", projectName).Equals("domain_id", domain.Id)
|
||||
err = q.First(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*SProject), err
|
||||
return obj.(*SProject), nil
|
||||
}
|
||||
|
||||
func (manager *SProjectManager) FetchProjectById(projectId string) (*SProject, error) {
|
||||
|
||||
@@ -90,6 +90,7 @@ func authUserByIdentity(ctx context.Context, ident mcclient.SAuthenticationIdent
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Query user")
|
||||
}
|
||||
ident.Password.User.Domain.Id = usr.DomainId
|
||||
idmap, err := models.IdmappingManager.FetchEntity(usr.Id, api.IdMappingEntityUser)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, errors.Wrap(err, "IdmappingManager.FetchEntity")
|
||||
|
||||
+12
-10
@@ -40,7 +40,8 @@ type AuthInfo struct {
|
||||
Username string
|
||||
Passwd string
|
||||
// Project is tenant when v2 auth
|
||||
Project string
|
||||
Project string
|
||||
ProjectDomain string
|
||||
}
|
||||
|
||||
func SetTimeout(t time.Duration) {
|
||||
@@ -48,16 +49,17 @@ func SetTimeout(t time.Duration) {
|
||||
}
|
||||
|
||||
func NewV2AuthInfo(authUrl, user, passwd, tenant string) *AuthInfo {
|
||||
return NewAuthInfo(authUrl, "", user, passwd, tenant)
|
||||
return NewAuthInfo(authUrl, "", user, passwd, tenant, "")
|
||||
}
|
||||
|
||||
func NewAuthInfo(authUrl, domain, user, passwd, project string) *AuthInfo {
|
||||
func NewAuthInfo(authUrl, domain, user, passwd, project, projectDomain string) *AuthInfo {
|
||||
return &AuthInfo{
|
||||
AuthUrl: authUrl,
|
||||
Domain: domain,
|
||||
Username: user,
|
||||
Passwd: passwd,
|
||||
Project: project,
|
||||
AuthUrl: authUrl,
|
||||
Domain: domain,
|
||||
Username: user,
|
||||
Passwd: passwd,
|
||||
Project: project,
|
||||
ProjectDomain: projectDomain,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,8 +156,8 @@ func (a *authManager) authAdmin() error {
|
||||
var token mcclient.TokenCredential
|
||||
var err error
|
||||
token, err = a.client.AuthenticateWithSource(
|
||||
a.info.Username, a.info.Passwd,
|
||||
a.info.Domain, a.info.Project, mcclient.AuthSourceSrv)
|
||||
a.info.Username, a.info.Passwd, a.info.Domain,
|
||||
a.info.Project, a.info.ProjectDomain, mcclient.AuthSourceSrv)
|
||||
if err != nil {
|
||||
log.Errorf("Admin auth failed: %s", err)
|
||||
return err
|
||||
|
||||
+19
-18
@@ -127,7 +127,7 @@ func (this *Client) jsonRequest(ctx context.Context, endpoint string, token stri
|
||||
return httputils.JSONRequest(this.httpconn, ctx, method, joinUrl(endpoint, url), getDefaultHeader(header, token), body, this.debug)
|
||||
}
|
||||
|
||||
func (this *Client) _authV3(domainName, uname, passwd, projectId, projectName, token string, aCtx SAuthContext) (TokenCredential, error) {
|
||||
func (this *Client) _authV3(domainName, uname, passwd, projectId, projectName, projectDomain, token string, aCtx SAuthContext) (TokenCredential, error) {
|
||||
input := SAuthenticationInputV3{}
|
||||
if len(uname) > 0 && len(passwd) > 0 { // Password authentication
|
||||
input.Auth.Identity.Methods = []string{api.AUTH_METHOD_PASSWORD}
|
||||
@@ -148,11 +148,12 @@ func (this *Client) _authV3(domainName, uname, passwd, projectId, projectName, t
|
||||
}
|
||||
if len(projectName) > 0 {
|
||||
input.Auth.Scope.Project.Name = projectName
|
||||
if len(domainName) > 0 {
|
||||
if len(projectDomain) > 0 {
|
||||
input.Auth.Scope.Project.Domain.Name = domainName
|
||||
} else {
|
||||
input.Auth.Scope.Project.Domain.Id = api.DEFAULT_DOMAIN_ID
|
||||
}
|
||||
// else {
|
||||
// input.Auth.Scope.Project.Domain.Id = api.DEFAULT_DOMAIN_ID
|
||||
// }
|
||||
}
|
||||
input.Auth.Context = aCtx
|
||||
hdr, rbody, err := this.jsonRequest(context.Background(), this.authUrl, "", "POST", "/auth/tokens", nil, jsonutils.Marshal(&input))
|
||||
@@ -189,32 +190,32 @@ func (this *Client) _authV2(uname, passwd, tenantId, tenantName, token string, a
|
||||
return this.unmarshalV2Token(rbody)
|
||||
}
|
||||
|
||||
func (this *Client) Authenticate(uname, passwd, domainName, tenantName string) (TokenCredential, error) {
|
||||
return this.AuthenticateApi(uname, passwd, domainName, tenantName)
|
||||
func (this *Client) Authenticate(uname, passwd, domainName, tenantName, tenantDomain string) (TokenCredential, error) {
|
||||
return this.AuthenticateApi(uname, passwd, domainName, tenantName, tenantDomain)
|
||||
}
|
||||
|
||||
func (this *Client) AuthenticateApi(uname, passwd, domainName, tenantName string) (TokenCredential, error) {
|
||||
return this.AuthenticateWithSource(uname, passwd, domainName, tenantName, AuthSourceAPI)
|
||||
func (this *Client) AuthenticateApi(uname, passwd, domainName, tenantName, tenantDomain string) (TokenCredential, error) {
|
||||
return this.AuthenticateWithSource(uname, passwd, domainName, tenantName, tenantDomain, AuthSourceAPI)
|
||||
}
|
||||
|
||||
func (this *Client) AuthenticateWeb(uname, passwd, domainName, tenantName string, cliIp string) (TokenCredential, error) {
|
||||
func (this *Client) AuthenticateWeb(uname, passwd, domainName, tenantName, tenantDomain string, cliIp string) (TokenCredential, error) {
|
||||
aCtx := SAuthContext{
|
||||
Source: AuthSourceWeb,
|
||||
Ip: cliIp,
|
||||
}
|
||||
return this.authenticateWithContext(uname, passwd, domainName, tenantName, aCtx)
|
||||
return this.authenticateWithContext(uname, passwd, domainName, tenantName, tenantDomain, aCtx)
|
||||
}
|
||||
|
||||
func (this *Client) AuthenticateWithSource(uname, passwd, domainName, tenantName string, source string) (TokenCredential, error) {
|
||||
func (this *Client) AuthenticateWithSource(uname, passwd, domainName, tenantName, tenantDomain string, source string) (TokenCredential, error) {
|
||||
aCtx := SAuthContext{
|
||||
Source: source,
|
||||
}
|
||||
return this.authenticateWithContext(uname, passwd, domainName, tenantName, aCtx)
|
||||
return this.authenticateWithContext(uname, passwd, domainName, tenantName, tenantDomain, aCtx)
|
||||
}
|
||||
|
||||
func (this *Client) authenticateWithContext(uname, passwd, domainName, tenantName string, aCtx SAuthContext) (TokenCredential, error) {
|
||||
func (this *Client) authenticateWithContext(uname, passwd, domainName, tenantName, tenantDomain string, aCtx SAuthContext) (TokenCredential, error) {
|
||||
if this.AuthVersion() == "v3" {
|
||||
return this._authV3(domainName, uname, passwd, "", tenantName, "", aCtx)
|
||||
return this._authV3(domainName, uname, passwd, "", tenantName, tenantDomain, "", aCtx)
|
||||
}
|
||||
return this._authV2(uname, passwd, "", tenantName, "", aCtx)
|
||||
}
|
||||
@@ -281,17 +282,17 @@ func (this *Client) Verify(adminToken, token string) (cred TokenCredential, err
|
||||
return this.verifyV2(adminToken, token)
|
||||
}
|
||||
|
||||
func (this *Client) SetTenant(tenantId, tenantName string, token TokenCredential) (TokenCredential, error) {
|
||||
return this.SetProject(tenantId, tenantName, token)
|
||||
func (this *Client) SetTenant(tenantId, tenantName, tenantDomain string, token TokenCredential) (TokenCredential, error) {
|
||||
return this.SetProject(tenantId, tenantName, tenantDomain, token)
|
||||
}
|
||||
|
||||
func (this *Client) SetProject(tenantId, tenantName string, token TokenCredential) (TokenCredential, error) {
|
||||
func (this *Client) SetProject(tenantId, tenantName, tenantDomain string, token TokenCredential) (TokenCredential, error) {
|
||||
aCtx := SAuthContext{
|
||||
Source: token.GetLoginSource(),
|
||||
Ip: token.GetLoginIp(),
|
||||
}
|
||||
if this.AuthVersion() == "v3" {
|
||||
return this._authV3("", "", "", tenantId, tenantName, token.GetTokenString(), aCtx)
|
||||
return this._authV3("", "", "", tenantId, tenantName, tenantDomain, token.GetTokenString(), aCtx)
|
||||
} else {
|
||||
return this._authV2("", "", "", tenantName, token.GetTokenString(), aCtx)
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ type SOpenStackClient struct {
|
||||
username string
|
||||
password string
|
||||
project string
|
||||
projectDomain string
|
||||
endpointType string
|
||||
domainName string
|
||||
client *mcclient.Client
|
||||
@@ -53,17 +54,18 @@ type SOpenStackClient struct {
|
||||
Debug bool
|
||||
}
|
||||
|
||||
func NewOpenStackClient(providerID string, providerName string, authURL string, username string, password string, project string, endpointType string, domainName string, isDebug bool) (*SOpenStackClient, error) {
|
||||
func NewOpenStackClient(providerID string, providerName string, authURL string, username string, password string, project string, endpointType string, domainName string, projectDomainName string, isDebug bool) (*SOpenStackClient, error) {
|
||||
cli := &SOpenStackClient{
|
||||
providerID: providerID,
|
||||
providerName: providerName,
|
||||
authURL: strings.TrimRight(authURL, "/"),
|
||||
username: username,
|
||||
password: password,
|
||||
project: project,
|
||||
endpointType: endpointType,
|
||||
domainName: domainName,
|
||||
Debug: isDebug,
|
||||
providerID: providerID,
|
||||
providerName: providerName,
|
||||
authURL: strings.TrimRight(authURL, "/"),
|
||||
username: username,
|
||||
password: password,
|
||||
project: project,
|
||||
projectDomain: projectDomainName,
|
||||
endpointType: endpointType,
|
||||
domainName: domainName,
|
||||
Debug: isDebug,
|
||||
}
|
||||
return cli, cli.fetchRegions()
|
||||
}
|
||||
@@ -192,7 +194,7 @@ func (cli *SOpenStackClient) getVersion(region string, service string) (string,
|
||||
|
||||
func (cli *SOpenStackClient) connect() error {
|
||||
cli.client = mcclient.NewClient(cli.authURL, 5, cli.Debug, false, "", "")
|
||||
tokenCredential, err := cli.client.Authenticate(cli.username, cli.password, cli.domainName, cli.project)
|
||||
tokenCredential, err := cli.client.Authenticate(cli.username, cli.password, cli.domainName, cli.project, cli.projectDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -112,11 +112,11 @@ func (self *SOpenStackProviderFactory) GetProvider(providerId, providerName, url
|
||||
if len(accountInfo) < 2 {
|
||||
return nil, fmt.Errorf("Missing username or project name %s", account)
|
||||
}
|
||||
project, username, endpointType, domainName := accountInfo[0], accountInfo[1], "internal", ""
|
||||
project, username, endpointType, domainName, projectDomainName := accountInfo[0], accountInfo[1], "internal", "", ""
|
||||
if len(accountInfo) == 3 {
|
||||
domainName = accountInfo[2]
|
||||
}
|
||||
client, err := openstack.NewOpenStackClient(providerId, providerName, url, username, password, project, endpointType, domainName, false)
|
||||
client, err := openstack.NewOpenStackClient(providerId, providerName, url, username, password, project, endpointType, domainName, projectDomainName, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user