2023-03-17 04:26:29 -04:00
|
|
|
/*
|
|
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
|
|
|
package openstack
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/url"
|
|
|
|
"regexp"
|
|
|
|
)
|
|
|
|
|
|
|
|
// AccountKey is a OpenStack account key.
|
|
|
|
type AccountKey struct {
|
|
|
|
AuthURL string
|
|
|
|
Username string
|
|
|
|
Password string
|
|
|
|
ProjectID string
|
|
|
|
ProjectName string
|
|
|
|
UserDomainName string
|
|
|
|
ProjectDomainName string
|
|
|
|
RegionName string
|
|
|
|
}
|
|
|
|
|
|
|
|
// AccountKeyFromURI parses ServiceAccountKey from URI.
|
|
|
|
func AccountKeyFromURI(serviceAccountURI string) (AccountKey, error) {
|
|
|
|
uri, err := url.Parse(serviceAccountURI)
|
|
|
|
if err != nil {
|
|
|
|
return AccountKey{}, err
|
|
|
|
}
|
|
|
|
if uri.Scheme != "serviceaccount" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: invalid scheme: %s", uri.Scheme)
|
|
|
|
}
|
|
|
|
if uri.Host != "openstack" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: invalid host: %s", uri.Host)
|
|
|
|
}
|
|
|
|
query := uri.Query()
|
|
|
|
if query.Get("auth_url") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"auth_url\": %s", uri)
|
|
|
|
}
|
|
|
|
if query.Get("username") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"username\": %s", uri)
|
|
|
|
}
|
|
|
|
if query.Get("password") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"password\": %s", uri)
|
|
|
|
}
|
|
|
|
if query.Get("project_id") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"project_id\": %s", uri)
|
|
|
|
}
|
|
|
|
if query.Get("project_name") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"project_name\": %s", uri)
|
|
|
|
}
|
|
|
|
if query.Get("user_domain_name") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"user_domain_name\": %s", uri)
|
|
|
|
}
|
|
|
|
if query.Get("project_domain_name") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"project_domain_name\": %s", uri)
|
|
|
|
}
|
|
|
|
if query.Get("region_name") == "" {
|
|
|
|
return AccountKey{}, fmt.Errorf("invalid service account URI: missing parameter \"region_name\": %s", uri)
|
|
|
|
}
|
|
|
|
return AccountKey{
|
|
|
|
AuthURL: query.Get("auth_url"),
|
|
|
|
Username: query.Get("username"),
|
|
|
|
Password: query.Get("password"),
|
|
|
|
ProjectID: query.Get("project_id"),
|
|
|
|
ProjectName: query.Get("project_name"),
|
|
|
|
UserDomainName: query.Get("user_domain_name"),
|
|
|
|
ProjectDomainName: query.Get("project_domain_name"),
|
|
|
|
RegionName: query.Get("region_name"),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToCloudServiceAccountURI converts the AccountKey into a cloud service account URI.
|
|
|
|
func (k AccountKey) ToCloudServiceAccountURI() string {
|
|
|
|
query := url.Values{}
|
|
|
|
query.Add("auth_url", k.AuthURL)
|
|
|
|
query.Add("username", k.Username)
|
|
|
|
query.Add("password", k.Password)
|
|
|
|
query.Add("project_id", k.ProjectID)
|
|
|
|
query.Add("project_name", k.ProjectName)
|
|
|
|
query.Add("user_domain_name", k.UserDomainName)
|
|
|
|
query.Add("project_domain_name", k.ProjectDomainName)
|
|
|
|
query.Add("region_name", k.RegionName)
|
|
|
|
uri := url.URL{
|
|
|
|
Scheme: "serviceaccount",
|
|
|
|
Host: "openstack",
|
|
|
|
RawQuery: query.Encode(),
|
|
|
|
}
|
|
|
|
return uri.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// CloudINI converts the AccountKey into a CloudINI.
|
|
|
|
func (k AccountKey) CloudINI() CloudINI {
|
|
|
|
return CloudINI{
|
|
|
|
AuthURL: k.AuthURL,
|
|
|
|
Username: k.Username,
|
|
|
|
Password: k.Password,
|
2023-05-02 03:35:52 -04:00
|
|
|
ProjectID: k.ProjectID,
|
2023-03-17 04:26:29 -04:00
|
|
|
TenantName: k.ProjectName,
|
|
|
|
UserDomainName: k.UserDomainName,
|
|
|
|
TenantDomainName: k.ProjectDomainName,
|
|
|
|
Region: k.RegionName,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CloudINI is a struct that represents the cloud.ini file used by OpenStack k8s deployments.
|
|
|
|
type CloudINI struct {
|
|
|
|
AuthURL string `gcfg:"auth-url" mapstructure:"auth-url" name:"os-authURL" dependsOn:"os-password|os-trustID|os-applicationCredentialSecret|os-clientCertPath"`
|
|
|
|
Username string `name:"os-userName" value:"optional" dependsOn:"os-password"`
|
|
|
|
Password string `name:"os-password" value:"optional" dependsOn:"os-domainID|os-domainName,os-projectID|os-projectName,os-userID|os-userName"`
|
2023-05-02 03:35:52 -04:00
|
|
|
ProjectID string `gcfg:"project-id" mapstructure:"project-id" name:"os-projectID" value:"optional" dependsOn:"os-password|os-clientCertPath"`
|
2023-03-17 04:26:29 -04:00
|
|
|
TenantName string `gcfg:"tenant-name" mapstructure:"project-name" name:"os-projectName" value:"optional" dependsOn:"os-password|os-clientCertPath"`
|
|
|
|
UserDomainName string `gcfg:"user-domain-name" mapstructure:"user-domain-name" name:"os-userDomainName" value:"optional"`
|
|
|
|
TenantDomainName string `gcfg:"tenant-domain-name" mapstructure:"project-domain-name" name:"os-projectDomainName" value:"optional"`
|
|
|
|
Region string `name:"os-region"`
|
|
|
|
}
|
|
|
|
|
2023-05-02 03:35:52 -04:00
|
|
|
// FullConfiguration returns the string representation of the full CloudINI.
|
|
|
|
func (i CloudINI) FullConfiguration() string {
|
2023-03-17 04:26:29 -04:00
|
|
|
// sanitize parameters to not include newlines
|
|
|
|
authURL := newlineRegexp.ReplaceAllString(i.AuthURL, "")
|
|
|
|
username := newlineRegexp.ReplaceAllString(i.Username, "")
|
|
|
|
password := newlineRegexp.ReplaceAllString(i.Password, "")
|
2023-05-02 03:35:52 -04:00
|
|
|
tenantID := newlineRegexp.ReplaceAllString(i.ProjectID, "")
|
2023-03-17 04:26:29 -04:00
|
|
|
tenantName := newlineRegexp.ReplaceAllString(i.TenantName, "")
|
|
|
|
userDomainName := newlineRegexp.ReplaceAllString(i.UserDomainName, "")
|
|
|
|
tenantDomainName := newlineRegexp.ReplaceAllString(i.TenantDomainName, "")
|
|
|
|
region := newlineRegexp.ReplaceAllString(i.Region, "")
|
|
|
|
|
|
|
|
return fmt.Sprintf(`[Global]
|
|
|
|
auth-url = %s
|
|
|
|
username = %s
|
|
|
|
password = %s
|
|
|
|
tenant-id = %s
|
|
|
|
tenant-name = %s
|
|
|
|
user-domain-name = %s
|
|
|
|
tenant-domain-name = %s
|
|
|
|
region = %s
|
|
|
|
`, authURL, username, password, tenantID, tenantName, userDomainName, tenantDomainName, region)
|
|
|
|
}
|
|
|
|
|
2023-05-02 03:35:52 -04:00
|
|
|
// YawolConfiguration returns the string representation of the CloudINI subset yawol expects.
|
|
|
|
func (i CloudINI) YawolConfiguration() string {
|
|
|
|
// sanitize parameters to not include newlines
|
|
|
|
authURL := newlineRegexp.ReplaceAllString(i.AuthURL, "")
|
|
|
|
username := newlineRegexp.ReplaceAllString(i.Username, "")
|
|
|
|
password := newlineRegexp.ReplaceAllString(i.Password, "")
|
|
|
|
projectID := newlineRegexp.ReplaceAllString(i.ProjectID, "")
|
|
|
|
userDomainName := newlineRegexp.ReplaceAllString(i.UserDomainName, "")
|
|
|
|
region := newlineRegexp.ReplaceAllString(i.Region, "")
|
|
|
|
|
|
|
|
return fmt.Sprintf(`[Global]
|
|
|
|
auth-url = %s
|
|
|
|
username = %s
|
|
|
|
password = %s
|
|
|
|
project-id = %s
|
|
|
|
domain-name = %s
|
|
|
|
region = %s
|
|
|
|
`, authURL, username, password, projectID, userDomainName, region)
|
|
|
|
}
|
|
|
|
|
2023-05-08 13:44:06 -04:00
|
|
|
// CinderCSIConfiguration returns the string representation of the CloudINI subset cinder expects.
|
|
|
|
func (i CloudINI) CinderCSIConfiguration() string {
|
|
|
|
// sanitize parameters to not include newlines
|
|
|
|
authURL := newlineRegexp.ReplaceAllString(i.AuthURL, "")
|
|
|
|
username := newlineRegexp.ReplaceAllString(i.Username, "")
|
|
|
|
password := newlineRegexp.ReplaceAllString(i.Password, "")
|
|
|
|
projectID := newlineRegexp.ReplaceAllString(i.ProjectID, "")
|
|
|
|
projectName := newlineRegexp.ReplaceAllString(i.TenantName, "")
|
|
|
|
userDomainName := newlineRegexp.ReplaceAllString(i.UserDomainName, "")
|
|
|
|
tenantDomainName := newlineRegexp.ReplaceAllString(i.TenantDomainName, "")
|
|
|
|
region := newlineRegexp.ReplaceAllString(i.Region, "")
|
|
|
|
|
|
|
|
return fmt.Sprintf(`[Global]
|
|
|
|
auth-url = %s
|
|
|
|
username = %s
|
|
|
|
password = %s
|
|
|
|
project-id = %s
|
|
|
|
project-name = %s
|
|
|
|
user-domain-name = %s
|
|
|
|
project-domain-name = %s
|
|
|
|
region = %s
|
|
|
|
`, authURL, username, password, projectID, projectName, userDomainName, tenantDomainName, region)
|
|
|
|
}
|
|
|
|
|
2023-03-17 04:26:29 -04:00
|
|
|
var newlineRegexp = regexp.MustCompile(`[\r\n]+`)
|