mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
keystone store service cert
This commit is contained in:
@@ -64,14 +64,15 @@ func init() {
|
||||
})
|
||||
|
||||
type EndpointCreateOptions struct {
|
||||
SERVICE string `help:"Service ID or Name"`
|
||||
REGION string `help:"Region"`
|
||||
INTERFACE string `help:"Interface types" choices:"internal|public|admin|console"`
|
||||
URL string `help:"URL"`
|
||||
Zone string `help:"Zone"`
|
||||
Name string `help:"Name"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
SERVICE string `help:"Service ID or Name"`
|
||||
REGION string `help:"Region"`
|
||||
INTERFACE string `help:"Interface types" choices:"internal|public|admin|console"`
|
||||
URL string `help:"URL"`
|
||||
Zone string `help:"Zone"`
|
||||
Name string `help:"Name"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
ServiceCertificate string `help:"Service certificate id or name"`
|
||||
}
|
||||
R(&EndpointCreateOptions{}, "endpoint-create", "Create endpoint", func(s *mcclient.ClientSession, args *EndpointCreateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -95,6 +96,9 @@ func init() {
|
||||
} else if !args.Enabled && args.Disabled {
|
||||
params.Add(jsonutils.JSONFalse, "enabled")
|
||||
}
|
||||
if len(args.ServiceCertificate) > 0 {
|
||||
params.Add(jsonutils.NewString(args.ServiceCertificate), "service_certificate")
|
||||
}
|
||||
ep, err := modules.EndpointsV3.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -104,11 +108,12 @@ func init() {
|
||||
})
|
||||
|
||||
type EndpointUpdateOptions struct {
|
||||
ID string `help:"ID or name of endpoint"`
|
||||
Url string `help:"URL"`
|
||||
Name string `help:"Name"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
ID string `help:"ID or name of endpoint"`
|
||||
Url string `help:"URL"`
|
||||
Name string `help:"Name"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
ServiceCertificate string `help:"Service certificate id or name"`
|
||||
}
|
||||
R(&EndpointUpdateOptions{}, "endpoint-update", "Update a endpoint", func(s *mcclient.ClientSession, args *EndpointUpdateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -123,6 +128,9 @@ func init() {
|
||||
} else if !args.Enabled && args.Disabled {
|
||||
params.Add(jsonutils.JSONFalse, "enabled")
|
||||
}
|
||||
if len(args.ServiceCertificate) > 0 {
|
||||
params.Add(jsonutils.NewString(args.ServiceCertificate), "service_certificate")
|
||||
}
|
||||
ep, err := modules.EndpointsV3.Patch(s, args.ID, params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
R(&options.ServiceCertificateCreateOptions{}, "service-cert-create", "Create service cert", func(s *mcclient.ClientSession, opts *options.ServiceCertificateCreateOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cert, err := modules.ServiceCertificatesV3.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(cert)
|
||||
return nil
|
||||
})
|
||||
type ServiceCertificateGetOptions struct {
|
||||
ID string `json:"-"`
|
||||
}
|
||||
R(&ServiceCertificateGetOptions{}, "service-cert-show", "Show service cert", func(s *mcclient.ClientSession, opts *ServiceCertificateGetOptions) error {
|
||||
cert, err := modules.ServiceCertificatesV3.Get(s, opts.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(cert)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ServiceCertificateListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
R(&ServiceCertificateListOptions{}, "service-cert-list", "List service certs", func(s *mcclient.ClientSession, opts *ServiceCertificateListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.ServiceCertificatesV3.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.ServiceCertificatesV3.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
type ServiceCertificateDeleteOptions struct {
|
||||
ID string `json:"-"`
|
||||
}
|
||||
R(&ServiceCertificateDeleteOptions{}, "service-cert-delete", "Delete service cert", func(s *mcclient.ClientSession, opts *ServiceCertificateDeleteOptions) error {
|
||||
cert, err := modules.ServiceCertificatesV3.Delete(s, opts.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(cert)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -1297,17 +1297,7 @@ type SLoadbalancerBackendgroupResourceBase struct {
|
||||
type SLoadbalancerCertificate struct {
|
||||
apis.SVirtualResourceBase
|
||||
apis.SExternalizedResourceBase
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKey string `json:"private_key"`
|
||||
// derived attributes
|
||||
PublicKeyAlgorithm string `json:"public_key_algorithm"`
|
||||
PublicKeyBitLen int `json:"public_key_bit_len"`
|
||||
SignatureAlgorithm string `json:"signature_algorithm"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
NotBefore time.Time `json:"not_before"`
|
||||
NotAfter time.Time `json:"not_after"`
|
||||
CommonName string `json:"common_name"`
|
||||
SubjectAlternativeNames string `json:"subject_alternative_names"`
|
||||
apis.SCertificateResourceBase
|
||||
}
|
||||
|
||||
// SLoadbalancerCertificateResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerCertificateResourceBase.
|
||||
|
||||
@@ -19,6 +19,7 @@ import "yunion.io/x/onecloud/pkg/apis"
|
||||
type EndpointDetails struct {
|
||||
apis.StandaloneResourceDetails
|
||||
SEndpoint
|
||||
CertificateDetails
|
||||
|
||||
// 服务名称,例如keystone, glance, region等
|
||||
ServiceName string `json:"service_name"`
|
||||
@@ -26,3 +27,12 @@ type EndpointDetails struct {
|
||||
// 服务类型,例如identity, image, compute等
|
||||
ServiceType string `json:"service_type"`
|
||||
}
|
||||
|
||||
type CertificateDetails struct {
|
||||
apis.SCertificateResourceBase
|
||||
CertName string `json:"cert_name"`
|
||||
CertId string `json:"cert_id"`
|
||||
|
||||
CaCertificate string `json:"ca_certificate"`
|
||||
CaPrivateKey string `json:"ca_private_key"`
|
||||
}
|
||||
|
||||
@@ -71,13 +71,14 @@ type SEnabledIdentityBaseResource struct {
|
||||
// SEndpoint is an autogenerated struct via yunion.io/x/onecloud/pkg/keystone/models.SEndpoint.
|
||||
type SEndpoint struct {
|
||||
apis.SStandaloneResourceBase
|
||||
LegacyEndpointId string `json:"legacy_endpoint_id"`
|
||||
Interface string `json:"interface"`
|
||||
ServiceId string `json:"service_id"`
|
||||
Url string `json:"url"`
|
||||
Extra interface{} `json:"extra"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
RegionId string `json:"region_id"`
|
||||
LegacyEndpointId string `json:"legacy_endpoint_id"`
|
||||
Interface string `json:"interface"`
|
||||
ServiceId string `json:"service_id"`
|
||||
Url string `json:"url"`
|
||||
Extra interface{} `json:"extra"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
RegionId string `json:"region_id"`
|
||||
ServiceCertificateId string `json:"service_certificate_id"`
|
||||
}
|
||||
|
||||
// SFederatedUser is an autogenerated struct via yunion.io/x/onecloud/pkg/keystone/models.SFederatedUser.
|
||||
@@ -188,6 +189,14 @@ type SService struct {
|
||||
Extra interface{} `json:"extra"`
|
||||
}
|
||||
|
||||
// SServiceCertificate is an autogenerated struct via yunion.io/x/onecloud/pkg/keystone/models.SServiceCertificate.
|
||||
type SServiceCertificate struct {
|
||||
apis.SStandaloneResourceBase
|
||||
apis.SCertificateResourceBase
|
||||
CaCertificate string `json:"ca_certificate"`
|
||||
CaPrivateKey string `json:"ca_private_key"`
|
||||
}
|
||||
|
||||
// SUser is an autogenerated struct via yunion.io/x/onecloud/pkg/keystone/models.SUser.
|
||||
type SUser struct {
|
||||
SEnabledIdentityBaseResource
|
||||
|
||||
@@ -24,6 +24,21 @@ type SAdminSharableVirtualResourceBase struct {
|
||||
Records string `json:"records"`
|
||||
}
|
||||
|
||||
// SCertificateResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudcommon/db.SCertificateResourceBase.
|
||||
type SCertificateResourceBase struct {
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKey string `json:"private_key"`
|
||||
// derived attributes
|
||||
PublicKeyAlgorithm string `json:"public_key_algorithm"`
|
||||
PublicKeyBitLen int `json:"public_key_bit_len"`
|
||||
SignatureAlgorithm string `json:"signature_algorithm"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
NotBefore time.Time `json:"not_before"`
|
||||
NotAfter time.Time `json:"not_after"`
|
||||
CommonName string `json:"common_name"`
|
||||
SubjectAlternativeNames string `json:"subject_alternative_names"`
|
||||
}
|
||||
|
||||
// SDomainLevelResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/cloudcommon/db.SDomainLevelResourceBase.
|
||||
type SDomainLevelResourceBase struct {
|
||||
SStandaloneResourceBase
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type SCertificateResourceBase struct {
|
||||
Certificate string `create:"required" list:"user" update:"user"`
|
||||
PrivateKey string `create:"required" list:"admin" update:"user"`
|
||||
|
||||
// derived attributes
|
||||
PublicKeyAlgorithm string `create:"optional" list:"user" update:"user"`
|
||||
PublicKeyBitLen int `create:"optional" list:"user" update:"user"`
|
||||
SignatureAlgorithm string `create:"optional" list:"user" update:"user"`
|
||||
Fingerprint string `create:"optional" list:"user" update:"user"`
|
||||
NotBefore time.Time `create:"optional" list:"user" update:"user"`
|
||||
NotAfter time.Time `create:"optional" list:"user" update:"user"`
|
||||
CommonName string `create:"optional" list:"user" update:"user"`
|
||||
SubjectAlternativeNames string `create:"optional" list:"user" update:"user"`
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
@@ -24,8 +25,12 @@ import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
)
|
||||
|
||||
type ValidatorPEM struct {
|
||||
@@ -372,3 +377,69 @@ func (v *ValidatorPrivateKey) MatchCertificate(cert *x509.Certificate) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ValidatorCertKey struct {
|
||||
*ValidatorCertificate
|
||||
*ValidatorPrivateKey
|
||||
|
||||
certPubKeyAlgo string
|
||||
}
|
||||
|
||||
func NewCertKeyValidator(cert, key string) *ValidatorCertKey {
|
||||
return &ValidatorCertKey{
|
||||
ValidatorCertificate: NewCertificateValidator(cert),
|
||||
ValidatorPrivateKey: NewPrivateKeyValidator(key),
|
||||
}
|
||||
}
|
||||
|
||||
func (v *ValidatorCertKey) Validate(data *jsonutils.JSONDict) error {
|
||||
keyV := map[string]IValidator{
|
||||
"certificate": v.ValidatorCertificate,
|
||||
"private_key": v.ValidatorPrivateKey,
|
||||
}
|
||||
for _, v := range keyV {
|
||||
if err := v.Validate(data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cert := v.ValidatorCertificate.Certificates[0]
|
||||
var certPubKeyAlgo string
|
||||
{
|
||||
// x509.PublicKeyAlgorithm.String() is only available since go1.10
|
||||
switch cert.PublicKeyAlgorithm {
|
||||
case x509.RSA:
|
||||
certPubKeyAlgo = api.LB_TLS_CERT_PUBKEY_ALGO_RSA
|
||||
case x509.ECDSA:
|
||||
certPubKeyAlgo = api.LB_TLS_CERT_PUBKEY_ALGO_ECDSA
|
||||
default:
|
||||
certPubKeyAlgo = fmt.Sprintf("algo %#v", cert.PublicKeyAlgorithm)
|
||||
}
|
||||
if !api.LB_TLS_CERT_PUBKEY_ALGOS.Has(certPubKeyAlgo) {
|
||||
return httperrors.NewInputParameterError("invalid cert pubkey algorithm: %s, want %s",
|
||||
certPubKeyAlgo, api.LB_TLS_CERT_PUBKEY_ALGOS.String())
|
||||
}
|
||||
}
|
||||
v.certPubKeyAlgo = certPubKeyAlgo
|
||||
if err := v.ValidatorPrivateKey.MatchCertificate(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *ValidatorCertKey) UpdateCertKeyInfo(ctx context.Context, data *jsonutils.JSONDict) *jsonutils.JSONDict {
|
||||
cert := v.ValidatorCertificate.Certificates[0]
|
||||
// NOTE subject alternative names also includes email, url, ip addresses,
|
||||
// but we ignore them here.
|
||||
//
|
||||
// NOTE we use white space to separate names
|
||||
data.Set("common_name", jsonutils.NewString(cert.Subject.CommonName))
|
||||
data.Set("subject_alternative_names", jsonutils.NewString(strings.Join(cert.DNSNames, " ")))
|
||||
|
||||
data.Set("not_before", jsonutils.NewTimeString(cert.NotBefore))
|
||||
data.Set("not_after", jsonutils.NewTimeString(cert.NotAfter))
|
||||
data.Set("public_key_algorithm", jsonutils.NewString(v.certPubKeyAlgo))
|
||||
data.Set("public_key_bit_len", jsonutils.NewInt(int64(v.ValidatorCertificate.PublicKeyBitLen())))
|
||||
data.Set("signature_algorithm", jsonutils.NewString(cert.SignatureAlgorithm.String()))
|
||||
data.Set("fingerprint", jsonutils.NewString(api.LB_TLS_CERT_FINGERPRINT_ALGO_SHA256+":"+v.ValidatorCertificate.FingerprintSha256String()))
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -13,3 +13,109 @@
|
||||
// limitations under the License.
|
||||
|
||||
package validators
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
func TestValidateCertKey_Validate(t *testing.T) {
|
||||
type fields struct {
|
||||
ValidatorCertificate *ValidatorCertificate
|
||||
ValidatorPrivateKey *ValidatorPrivateKey
|
||||
certPubKeyAlgo string
|
||||
}
|
||||
type args struct {
|
||||
data *jsonutils.JSONDict
|
||||
}
|
||||
cert := `-----BEGIN CERTIFICATE-----
|
||||
MIIDEDCCAfigAwIBAgIIPfkszEMuuikwDQYJKoZIhvcNAQELBQAwEzERMA8GA1UE
|
||||
AxMIb25lY2xvdWQwHhcNMjAwMTAzMTEwMzA3WhcNMjIwMzEzMTEwMzA3WjASMRAw
|
||||
DgYDVQQDEwdzZXJ2aWNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
phzvJJ3grosTiPBmmip6OpLkOezhbyuYbDGhynDH9N3+BWOQsPjzkigMhQjoygzH
|
||||
G3Ac4f6yUJEzThTlkEckEVvxKftXTX+u2/F4SnaF61wiLA8SD2nXtYFNUhaOQ9Bo
|
||||
vIcUlI/6idcxUZiktbAHv9FnawfNk1n6ryEy8LXPWS5RP+GhQfQG0Zko9APvLr/4
|
||||
OB9zqgzc8+LUppxYtLMoy42FJ/OZhnGo31BWB9RW2WML+oO6J+uxt0JQGJwp8vr0
|
||||
8OpSp5rgbu8G5jDlCOj4hEctbflJus/ES2jaR0etOcVSt+GYeTrKPmX9pPZ4TS9A
|
||||
C1Lok0RR1xiDTS7Gw6pGnwIDAQABo2kwZzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l
|
||||
BAwwCgYIKwYBBQUHAwEwQAYDVR0RBDkwN4IHc2VydmljZYIQc2VydmljZS5vbmVj
|
||||
bG91ZIIUc2VydmljZS5vbmVjbG91ZC5zdmOHBAqo3pYwDQYJKoZIhvcNAQELBQAD
|
||||
ggEBAHYS4p2UrJ977SYFYYpsrE6Q01XSG6qt9EDTT9iB5GA/viuLURVHUMQDxKnf
|
||||
2hSMq/UV+pGfGBw0Ki2sd+Mylb9qi59c26Ogqe8N/v+c219bYdnN7IzAgLQsEOd8
|
||||
3iEJ7Ypb5pgf3B/dBPyWzxmKjZQ7vIfLYWgbmigPtf29yCWd3AlZrhI9zQUEcq7D
|
||||
EAqtcvpU5/y7QsBNXo0QJa1WeeAOzYnKHUPQBJU4qLPm305BDHhKFyY23jsRSQMO
|
||||
3CTjx9YsN9qGnv+oaqleA/ua/4f0QoPEQMXUsN1FGsAsC+vcKwDodY6vIvFnAk6o
|
||||
pYTlCl+Ls6/Bu/Oml8AvrlaEyuc=
|
||||
-----END CERTIFICATE-----`
|
||||
pkey := `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAphzvJJ3grosTiPBmmip6OpLkOezhbyuYbDGhynDH9N3+BWOQ
|
||||
sPjzkigMhQjoygzHG3Ac4f6yUJEzThTlkEckEVvxKftXTX+u2/F4SnaF61wiLA8S
|
||||
D2nXtYFNUhaOQ9BovIcUlI/6idcxUZiktbAHv9FnawfNk1n6ryEy8LXPWS5RP+Gh
|
||||
QfQG0Zko9APvLr/4OB9zqgzc8+LUppxYtLMoy42FJ/OZhnGo31BWB9RW2WML+oO6
|
||||
J+uxt0JQGJwp8vr08OpSp5rgbu8G5jDlCOj4hEctbflJus/ES2jaR0etOcVSt+GY
|
||||
eTrKPmX9pPZ4TS9AC1Lok0RR1xiDTS7Gw6pGnwIDAQABAoIBAHqbvrQDSBTtGIUq
|
||||
FEFUexWC2KwcuSSqQ/4QAECBUEXgGR/3JpRJnNbTcrI7KkAAgHIzJU52BT3Mftby
|
||||
O6NrryaU+4OmPgE47mLvb39ezmgzgBGPKiBwWkRhZSXi+iz5xmTpO3qQbzeQu5lj
|
||||
lqd4f6/Iq5Hnl4hckNj1IzliqOJEShiYQV69NADbUsnmruHL3Mt3f3SQI9yv+k48
|
||||
5QMGol0eIuFkur6+I0mryvfx36gqHOsZIRweAMPGmGLr+aatrsXfV1pHON/4FhPY
|
||||
dOSEpVz2hOPt9HMMy8AJXjMDvl8RfaW/T7NY+2lJoE4IMcxuGOqQRGnnBRioOuP9
|
||||
lnuTbnECgYEAxq79lGJb5oasmk277Z+8h7BF9lHMDo6jah8cEGL5lTS4u7SYcLHp
|
||||
uL9WBDoAhdVX2XULF13D+NPXQObySr96oGXJxlAtxSpRjURAGlLIn4Y3rth+RUT/
|
||||
k+N7QkS78wfUCf71icnXr71SqctVC6tJnqgvxF5JP+Cy4P1BuSYcPEkCgYEA1giS
|
||||
f17Q3t1iWmNGLRb+J6JQeYoQyFDPX/ROz0Ko7Nf1svzYLTWrjJGjXXw8/vUOs0pP
|
||||
M7yV2TFzLT7nGuDBfwFVU4Kv3JNU5x+Z6++g7tv3/3JiKG0QXQvwNPbYVHrWj1cf
|
||||
T15HyVNZwibydEl0Q6HdZpzZP2cxg3Jm9kVJW6cCgYAdOMmVFG5d1nr2au50AaVx
|
||||
84wmsVso3PPN/OtcwaHhvxJYkTRGhvRQNtwI3RsMlBdKpXtPIXxcUZP8OLt0IPuB
|
||||
MddecpZ4xEOgWmRvOrPFOrFf5vmTaJWKg8+yLHfUQ9d87OHiNSyi7V6GGKDWiYfX
|
||||
bPcxk4iEe6DzlGwhNii6+QKBgQDF38T4poL6F7gvEmq1kvVDVSeLRd6AI12lO2uE
|
||||
5/7egEXxxRpiqaTA34AmFI8bsxl1HjUdArOSycnOwcHNMo8RSP1GqKLHjRpIVwnp
|
||||
e2/QhGLBslEXSMWBEGFxxeh4KdylRol2yhYaBcoM2g76/VHUmRfkHwwmNtQqzyBr
|
||||
e+D3LwKBgE2fGOe5rqZ8/mCJcx7Wlt8gqD66WUhGqMh3pd4Om6ZGFVLvhPWEu3Md
|
||||
57oFd4cQZ6FSIOKb+cFIpCIW8sXG+c3vFjIC5PDMnSPbasF5KHN/Kg3C+p2ilviv
|
||||
Oycn3Dy2jpdE7SpoBCt3HsIhra8a6h7BcCQ87UwObqTsdLe+7/oD
|
||||
-----END RSA PRIVATE KEY-----`
|
||||
var data = jsonutils.NewDict()
|
||||
data.Set("certificate", jsonutils.NewString(cert))
|
||||
data.Set("private_key", jsonutils.NewString(pkey))
|
||||
var data2 = jsonutils.NewDict()
|
||||
data2.Set("certificate", jsonutils.NewString(cert+"error"))
|
||||
data2.Set("private_key", jsonutils.NewString(pkey+"error"))
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "good in",
|
||||
fields: fields{
|
||||
ValidatorCertificate: NewCertificateValidator("certificate"),
|
||||
ValidatorPrivateKey: NewPrivateKeyValidator("private_key"),
|
||||
},
|
||||
args: args{data},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "bad in",
|
||||
fields: fields{
|
||||
ValidatorCertificate: NewCertificateValidator("certificate"),
|
||||
ValidatorPrivateKey: NewPrivateKeyValidator("private_key"),
|
||||
},
|
||||
args: args{data2},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := &ValidatorCertKey{
|
||||
ValidatorCertificate: tt.fields.ValidatorCertificate,
|
||||
ValidatorPrivateKey: tt.fields.ValidatorPrivateKey,
|
||||
certPubKeyAlgo: tt.fields.certPubKeyAlgo,
|
||||
}
|
||||
if err := v.Validate(tt.args.data); (err != nil) != tt.wantErr {
|
||||
t.Errorf("ValidateCertKey.Validator() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -70,18 +68,7 @@ type SLoadbalancerCertificate struct {
|
||||
// SManagedResourceBase
|
||||
// SCloudregionResourceBase
|
||||
|
||||
Certificate string `create:"required" list:"user" update:"user"`
|
||||
PrivateKey string `create:"required" list:"admin" update:"user"`
|
||||
|
||||
// derived attributes
|
||||
PublicKeyAlgorithm string `create:"optional" list:"user" update:"user"`
|
||||
PublicKeyBitLen int `create:"optional" list:"user" update:"user"`
|
||||
SignatureAlgorithm string `create:"optional" list:"user" update:"user"`
|
||||
Fingerprint string `create:"optional" list:"user" update:"user"`
|
||||
NotBefore time.Time `create:"optional" list:"user" update:"user"`
|
||||
NotAfter time.Time `create:"optional" list:"user" update:"user"`
|
||||
CommonName string `create:"optional" list:"user" update:"user"`
|
||||
SubjectAlternativeNames string `create:"optional" list:"user" update:"user"`
|
||||
db.SCertificateResourceBase
|
||||
}
|
||||
|
||||
func (lbcert *SLoadbalancerCertificate) GetCachedCerts() ([]SCachedLoadbalancerCertificate, error) {
|
||||
@@ -201,55 +188,6 @@ func (lbcert *SLoadbalancerCertificate) Delete(ctx context.Context, userCred mcc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (man *SLoadbalancerCertificateManager) validateCertKey(ctx context.Context, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
certV := validators.NewCertificateValidator("certificate")
|
||||
pkeyV := validators.NewPrivateKeyValidator("private_key")
|
||||
keyV := map[string]validators.IValidator{
|
||||
"certificate": certV,
|
||||
"private_key": pkeyV,
|
||||
}
|
||||
for _, v := range keyV {
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
cert := certV.Certificates[0]
|
||||
var certPubKeyAlgo string
|
||||
{
|
||||
// x509.PublicKeyAlgorithm.String() is only available since go1.10
|
||||
switch cert.PublicKeyAlgorithm {
|
||||
case x509.RSA:
|
||||
certPubKeyAlgo = api.LB_TLS_CERT_PUBKEY_ALGO_RSA
|
||||
case x509.ECDSA:
|
||||
certPubKeyAlgo = api.LB_TLS_CERT_PUBKEY_ALGO_ECDSA
|
||||
default:
|
||||
certPubKeyAlgo = fmt.Sprintf("algo %#v", cert.PublicKeyAlgorithm)
|
||||
}
|
||||
if !api.LB_TLS_CERT_PUBKEY_ALGOS.Has(certPubKeyAlgo) {
|
||||
return nil, httperrors.NewInputParameterError("invalid cert pubkey algorithm: %s, want %s",
|
||||
certPubKeyAlgo, api.LB_TLS_CERT_PUBKEY_ALGOS.String())
|
||||
}
|
||||
}
|
||||
err := pkeyV.MatchCertificate(cert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// NOTE subject alternative names also includes email, url, ip addresses,
|
||||
// but we ignore them here.
|
||||
//
|
||||
// NOTE we use white space to separate names
|
||||
data.Set("common_name", jsonutils.NewString(cert.Subject.CommonName))
|
||||
data.Set("subject_alternative_names", jsonutils.NewString(strings.Join(cert.DNSNames, " ")))
|
||||
|
||||
data.Set("not_before", jsonutils.NewTimeString(cert.NotBefore))
|
||||
data.Set("not_after", jsonutils.NewTimeString(cert.NotAfter))
|
||||
data.Set("public_key_algorithm", jsonutils.NewString(certPubKeyAlgo))
|
||||
data.Set("public_key_bit_len", jsonutils.NewInt(int64(certV.PublicKeyBitLen())))
|
||||
data.Set("signature_algorithm", jsonutils.NewString(cert.SignatureAlgorithm.String()))
|
||||
data.Set("fingerprint", jsonutils.NewString(api.LB_TLS_CERT_FINGERPRINT_ALGO_SHA256+":"+certV.FingerprintSha256String()))
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (man *SLoadbalancerCertificateManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
@@ -335,13 +273,14 @@ func (man *SLoadbalancerCertificateManager) QueryDistinctExtraField(q *sqlchemy.
|
||||
}
|
||||
|
||||
func (man *SLoadbalancerCertificateManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := man.validateCertKey(ctx, data)
|
||||
if err != nil {
|
||||
v := validators.NewCertKeyValidator("certificate", "private_key")
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = v.UpdateCertKeyInfo(ctx, data)
|
||||
|
||||
input := apis.VirtualResourceCreateInput{}
|
||||
err = data.Unmarshal(&input)
|
||||
err := data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
|
||||
}
|
||||
|
||||
@@ -73,13 +73,14 @@ func init() {
|
||||
type SEndpoint struct {
|
||||
db.SStandaloneResourceBase
|
||||
|
||||
LegacyEndpointId string `width:"64" charset:"ascii" nullable:"true"`
|
||||
Interface string `width:"8" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"`
|
||||
ServiceId string `width:"64" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"`
|
||||
Url string `charset:"utf8" nullable:"false" list:"admin" update:"admin" create:"admin_required"`
|
||||
Extra *jsonutils.JSONDict `nullable:"true"`
|
||||
Enabled tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
RegionId string `width:"255" charset:"utf8" nullable:"true" list:"admin" create:"admin_required"`
|
||||
LegacyEndpointId string `width:"64" charset:"ascii" nullable:"true"`
|
||||
Interface string `width:"8" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"`
|
||||
ServiceId string `width:"64" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"`
|
||||
Url string `charset:"utf8" nullable:"false" list:"admin" update:"admin" create:"admin_required"`
|
||||
Extra *jsonutils.JSONDict `nullable:"true"`
|
||||
Enabled tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
RegionId string `width:"255" charset:"utf8" nullable:"true" list:"admin" create:"admin_required"`
|
||||
ServiceCertificateId string `nullable:"true" create:"admin_optional" update:"admin"`
|
||||
}
|
||||
|
||||
func (manager *SEndpointManager) InitializeData() error {
|
||||
@@ -245,7 +246,23 @@ func (endpoint *SEndpoint) GetExtraDetails(
|
||||
query jsonutils.JSONObject,
|
||||
isList bool,
|
||||
) (api.EndpointDetails, error) {
|
||||
return api.EndpointDetails{}, nil
|
||||
res, err := endpoint.getMoreDetails(api.EndpointDetails{})
|
||||
if err != nil {
|
||||
return api.EndpointDetails{}, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (endpoint *SEndpoint) getMoreDetails(details api.EndpointDetails) (api.EndpointDetails, error) {
|
||||
if len(endpoint.ServiceCertificateId) > 0 {
|
||||
icert, _ := ServiceCertificateManager.FetchById(endpoint.ServiceCertificateId)
|
||||
if icert != nil {
|
||||
cert := icert.(*SServiceCertificate)
|
||||
certOutput := cert.ToOutput()
|
||||
details.CertificateDetails = *certOutput
|
||||
}
|
||||
}
|
||||
return details, nil
|
||||
}
|
||||
|
||||
func (manager *SEndpointManager) FetchCustomizeColumns(
|
||||
@@ -266,6 +283,8 @@ func (manager *SEndpointManager) FetchCustomizeColumns(
|
||||
}
|
||||
ep := objs[i].(*SEndpoint)
|
||||
serviceIds = stringutils2.Append(serviceIds, ep.ServiceId)
|
||||
ep.SetModelManager(manager, ep)
|
||||
rows[i], _ = ep.getMoreDetails(rows[i])
|
||||
}
|
||||
if len(fields) == 0 || fields.Contains("service_name") || fields.Contains("service_type") {
|
||||
svs := fetchServices(serviceIds)
|
||||
@@ -307,7 +326,10 @@ func (endpoint *SEndpoint) ValidateDeleteCondition(ctx context.Context) error {
|
||||
return endpoint.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (manager *SEndpointManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
func (manager *SEndpointManager) ValidateCreateData(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject, data *jsonutils.JSONDict,
|
||||
) (*jsonutils.JSONDict, error) {
|
||||
infname, _ := data.GetString("interface")
|
||||
if len(infname) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("missing input field interface")
|
||||
@@ -330,6 +352,17 @@ func (manager *SEndpointManager) ValidateCreateData(ctx context.Context, userCre
|
||||
} else {
|
||||
return nil, httperrors.NewInputParameterError("missing input field service/service_id")
|
||||
}
|
||||
if certId, _ := data.GetString("service_certificate"); len(certId) > 0 {
|
||||
cert, err := ServiceCertificateManager.FetchByIdOrName(userCred, certId)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewNotFoundError("not found cert %s", certId)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Set("service_certificate_id", jsonutils.NewString(cert.GetId()))
|
||||
}
|
||||
|
||||
input := apis.StandaloneResourceCreateInput{}
|
||||
err := data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
@@ -433,3 +466,20 @@ func (endpoint *SEndpoint) PostDelete(ctx context.Context, userCred mcclient.Tok
|
||||
logclient.AddActionLogWithContext(ctx, endpoint, logclient.ACT_DELETE, nil, userCred, true)
|
||||
refreshDefaultClientServiceCatalog()
|
||||
}
|
||||
|
||||
func (endpoint *SEndpoint) ValidateUpdateData(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data *jsonutils.JSONDict,
|
||||
) (*jsonutils.JSONDict, error) {
|
||||
if certId, _ := data.GetString("service_certificate"); len(certId) > 0 {
|
||||
cert, err := ServiceCertificateManager.FetchByIdOrName(userCred, certId)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewNotFoundError("not found cert %s", certId)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Set("service_certificate_id", jsonutils.NewString(cert.GetId()))
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/identity"
|
||||
"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"
|
||||
)
|
||||
|
||||
type SServiceCertificateManager struct {
|
||||
db.SStandaloneResourceBaseManager
|
||||
}
|
||||
|
||||
var ServiceCertificateManager *SServiceCertificateManager
|
||||
|
||||
func init() {
|
||||
ServiceCertificateManager = &SServiceCertificateManager{
|
||||
SStandaloneResourceBaseManager: db.NewStandaloneResourceBaseManager(
|
||||
SServiceCertificate{},
|
||||
"servicecertificates_tbl",
|
||||
"servicecertificate",
|
||||
"servicecertificates",
|
||||
),
|
||||
}
|
||||
ServiceCertificateManager.SetVirtualObject(ServiceCertificateManager)
|
||||
}
|
||||
|
||||
type SServiceCertificate struct {
|
||||
db.SStandaloneResourceBase
|
||||
db.SCertificateResourceBase
|
||||
|
||||
CaCertificate string `create:"optional" list:"admin"`
|
||||
CaPrivateKey string `create:"optional" list:"admin"`
|
||||
}
|
||||
|
||||
func (man *SServiceCertificateManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
v := validators.NewCertKeyValidator("certificate", "private_key")
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = v.UpdateCertKeyInfo(ctx, data)
|
||||
|
||||
// validate ca cert key
|
||||
v = validators.NewCertKeyValidator("ca_certificate", "ca_private_key")
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
input := apis.StandaloneResourceCreateInput{}
|
||||
err := data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
|
||||
}
|
||||
input, err = man.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (cert *SServiceCertificate) ValidateUpdateData(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data *jsonutils.JSONDict,
|
||||
) (*jsonutils.JSONDict, error) {
|
||||
v := validators.NewCertKeyValidator("certificate", "private_key")
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = v.UpdateCertKeyInfo(ctx, data)
|
||||
|
||||
// validate ca cert key
|
||||
v = validators.NewCertKeyValidator("ca_certificate", "ca_private_key")
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updateData := jsonutils.NewDict()
|
||||
if name, err := data.GetString("name"); err == nil {
|
||||
updateData.Set("name", jsonutils.NewString(name))
|
||||
}
|
||||
|
||||
if desc, err := data.GetString("description"); err == nil {
|
||||
updateData.Set("description", jsonutils.NewString(desc))
|
||||
}
|
||||
|
||||
input := apis.StandaloneResourceBaseUpdateInput{}
|
||||
err := updateData.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unmarshal")
|
||||
}
|
||||
input, err = cert.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
updateData.Update(jsonutils.Marshal(input))
|
||||
|
||||
return updateData, nil
|
||||
}
|
||||
|
||||
func (cert *SServiceCertificate) ToOutput() *api.CertificateDetails {
|
||||
return &api.CertificateDetails{
|
||||
SCertificateResourceBase: apis.SCertificateResourceBase{
|
||||
Certificate: cert.Certificate,
|
||||
PrivateKey: cert.PrivateKey,
|
||||
PublicKeyAlgorithm: cert.PublicKeyAlgorithm,
|
||||
PublicKeyBitLen: cert.PublicKeyBitLen,
|
||||
SignatureAlgorithm: cert.SignatureAlgorithm,
|
||||
Fingerprint: cert.Fingerprint,
|
||||
NotAfter: cert.NotAfter,
|
||||
NotBefore: cert.NotBefore,
|
||||
CommonName: cert.CommonName,
|
||||
SubjectAlternativeNames: cert.SubjectAlternativeNames,
|
||||
},
|
||||
CertName: cert.Name,
|
||||
CertId: cert.Id,
|
||||
CaCertificate: cert.CaCertificate,
|
||||
CaPrivateKey: cert.CaPrivateKey,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -88,6 +88,7 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.PolicyManager,
|
||||
models.CredentialManager,
|
||||
models.IdentityProviderManager,
|
||||
models.ServiceCertificateManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package modules
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
|
||||
var (
|
||||
ServiceCertificatesV3 modulebase.ResourceManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
ServiceCertificatesV3 = NewIdentityV3Manager(
|
||||
"servicecertificate", "servicecertificates",
|
||||
[]string{
|
||||
"id",
|
||||
"name",
|
||||
"algorithm",
|
||||
"fingerprint",
|
||||
"not_before",
|
||||
"not_after",
|
||||
"common_name",
|
||||
"subject_alternative_names",
|
||||
},
|
||||
[]string{"tenant"},
|
||||
)
|
||||
|
||||
register(&ServiceCertificatesV3)
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
type ServiceCertificateCreateOptions struct {
|
||||
NAME string
|
||||
|
||||
Cert string `required:"true" json:"-" help:"path to certificate file"`
|
||||
Pkey string `required:"true" json:"-" help:"path to private key file"`
|
||||
CaCert string `help:"path to ca certificate file" json:"-"`
|
||||
CaPkey string `help:"paht to ca private key file" json:"-"`
|
||||
}
|
||||
|
||||
func serviceCertificateLoadFiles(pathM map[string]string, allowEmpty bool) (*jsonutils.JSONDict, error) {
|
||||
params := jsonutils.NewDict()
|
||||
for fieldName, path := range pathM {
|
||||
if path == "" {
|
||||
if allowEmpty {
|
||||
continue
|
||||
} else {
|
||||
return nil, fmt.Errorf("%s: empty path", fieldName)
|
||||
}
|
||||
}
|
||||
d, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: read %s: %s", fieldName, path, err)
|
||||
}
|
||||
if len(d) == 0 {
|
||||
return nil, fmt.Errorf("%s: empty file %s", fieldName, path)
|
||||
}
|
||||
params.Set(fieldName, jsonutils.NewString(string(d)))
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (opts *ServiceCertificateCreateOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
params, err := StructToParams(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pathM := map[string]string{
|
||||
"certificate": opts.Cert,
|
||||
"private_key": opts.Pkey,
|
||||
}
|
||||
paramsCertKey, err := serviceCertificateLoadFiles(pathM, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Update(paramsCertKey)
|
||||
|
||||
pathM = map[string]string{
|
||||
"ca_certificate": opts.CaCert,
|
||||
"ca_private_key": opts.CaPkey,
|
||||
}
|
||||
paramsCertKey, err = serviceCertificateLoadFiles(pathM, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Update(paramsCertKey)
|
||||
return params, nil
|
||||
}
|
||||
Reference in New Issue
Block a user