keystone store service cert

This commit is contained in:
wanyaoqi
2020-04-21 16:11:57 +08:00
parent fd67654377
commit bffb8eec65
15 changed files with 605 additions and 106 deletions
+21 -13
View File
@@ -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
+60
View File
@@ -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
})
}
+1 -11
View File
@@ -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.
+10
View File
@@ -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"`
}
+16 -7
View File
@@ -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
+15
View File
@@ -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
+20
View File
@@ -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)
}
})
}
}
+5 -66
View File
@@ -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)
}
+59 -9
View File
@@ -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
}
+128
View File
@@ -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,
}
}
+1
View File
@@ -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
}