| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package qcloud
- import (
- "crypto/sha1"
- "fmt"
- "strconv"
- "strings"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/cloudmux/pkg/apis"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/cloudmux/pkg/multicloud"
- )
- var CERT_STATUS_MAP = map[int]string{
- 0: "pending",
- 1: "normal",
- 2: "deleted",
- 3: "expired",
- 4: "normal",
- 5: "pending",
- 6: "deleted",
- 7: "deleted",
- 8: "pending",
- }
- type projectInfo struct {
- ProjectID string `json:"projectId"`
- OwnerUin int64 `json:"ownerUin"`
- Name string `json:"name"`
- CreatorUin int64 `json:"creatorUin"`
- CreateTime string `json:"createTime"`
- Info string `json:"info"`
- }
- // https://cloud.tencent.com/document/api/400/13675
- type SCertificate struct {
- multicloud.SCertificateBase
- QcloudTags
- client *SQcloudClient
- CertificateID string `json:"CertificateId"`
- CertificateType string `json:"CertificateType"`
- Deployable bool `json:"Deployable"`
- RenewAble bool `json:"RenewAble"`
- OwnerUin string `json:"ownerUin"`
- ProjectID string `json:"projectId"`
- From string `json:"from"`
- ProductZhName string `json:"productZhName"`
- Domain string `json:"domain"`
- Alias string `json:"alias"`
- Status int `json:"status"`
- VulnerabilityStatus string `json:"vulnerability_status"`
- CERTBeginTime time.Time `json:"certBeginTime"`
- CERTEndTime time.Time `json:"certEndTime"`
- ValidityPeriod string `json:"validityPeriod"`
- InsertTime string `json:"insertTime"`
- ProjectInfo projectInfo `json:"projectInfo"`
- StatusName string `json:"status_name"`
- IsVip bool `json:"is_vip"`
- IsDv bool `json:"is_dv"`
- IsWildcard bool `json:"is_wildcard"`
- IsVulnerability bool `json:"is_vulnerability"`
- // certificate details
- DetailsInitd bool `json:"details_initd"`
- SubjectAltName []string `json:"subjectAltName"`
- CertificatePrivateKey string `json:"CertificatePrivateKey"`
- CertificatePublicKey string `json:"CertificatePublicKey"`
- CertFingerprint string `json:"CertFingerprint"`
- }
- func (self *SCertificate) GetDetails() (*SCertificate, error) {
- if !self.DetailsInitd {
- var (
- cert *SCertificate
- err error
- )
- cert, err = self.client.GetCertificate(self.GetId())
- if err != nil {
- return nil, err
- }
- self.DetailsInitd = true
- self.SubjectAltName = cert.SubjectAltName
- self.CertificatePrivateKey = cert.CertificatePrivateKey
- self.CertificatePublicKey = cert.CertificatePublicKey
- self.CertFingerprint = cert.CertFingerprint
- }
- return self, nil
- }
- func (self *SCertificate) GetPublickKey() string {
- self.GetDetails()
- return self.CertificatePublicKey
- }
- func (self *SCertificate) GetPrivateKey() string {
- self.GetDetails()
- return self.CertificatePrivateKey
- }
- func (self *SCertificate) GetCert() string {
- self.GetDetails()
- return self.CertificatePublicKey
- }
- func (self *SCertificate) GetKey() string {
- self.GetDetails()
- return self.CertificatePrivateKey
- }
- func (self *SCertificate) Delete() error {
- return self.client.DeleteCertificate(self.GetId())
- }
- func (self *SCertificate) GetId() string {
- return self.CertificateID
- }
- func (self *SCertificate) GetName() string {
- if len(self.Alias) > 0 {
- return self.Alias
- } else {
- return self.Domain
- }
- }
- func (self *SCertificate) GetGlobalId() string {
- return self.CertificateID
- }
- func (self *SCertificate) GetStatus() string {
- status, ok := CERT_STATUS_MAP[self.Status]
- if !ok {
- return apis.STATUS_UNKNOWN
- }
- switch status {
- case "normal":
- return apis.STATUS_AVAILABLE
- case "deleted":
- return apis.STATUS_DELETING
- case "pending":
- return apis.STATUS_CREATING
- default:
- return status
- }
- }
- func (self *SCertificate) Refresh() error {
- cert, err := self.client.GetCertificate(self.GetId())
- if err != nil {
- return errors.Wrap(err, "GetCertificate")
- }
- return jsonutils.Update(self, cert)
- }
- func (self *SCertificate) GetCommonName() string {
- return self.Domain
- }
- func (self *SCertificate) GetSubjectAlternativeNames() string {
- self.GetDetails()
- return self.CertFingerprint
- }
- func (self *SCertificate) GetFingerprint() string {
- self.GetDetails()
- _fp := sha1.Sum([]byte(self.CertificatePublicKey))
- fp := fmt.Sprintf("sha1:% x", _fp)
- return strings.Replace(fp, " ", ":", -1)
- }
- func (self *SCertificate) GetExpireTime() time.Time {
- return self.CERTEndTime
- }
- func (self *SCertificate) GetProjectId() string {
- return self.ProjectID
- }
- func (self *SCertificate) GetSans() string {
- return strings.Join(self.SubjectAltName, ",")
- }
- func (self *SCertificate) GetStartDate() time.Time {
- return self.CERTBeginTime
- }
- func (self *SCertificate) GetProvince() string {
- return ""
- }
- func (self *SCertificate) GetCommon() string {
- return self.Domain
- }
- func (self *SCertificate) GetCountry() string {
- return ""
- }
- func (self *SCertificate) GetIssuer() string {
- return self.ProductZhName
- }
- func (self *SCertificate) GetEndDate() time.Time {
- return self.CERTEndTime
- }
- func (self *SCertificate) GetCity() string {
- return ""
- }
- func (self *SCertificate) GetOrgName() string {
- return ""
- }
- func (self *SCertificate) GetIsUpload() bool {
- if self.From == "upload" {
- return true
- }
- return false
- }
- // https://cloud.tencent.com/document/product/400/41674
- func (self *SQcloudClient) GetCertificate(certId string) (*SCertificate, error) {
- params := map[string]string{
- "CertificateId": certId,
- }
- resp, err := self.sslRequest("DescribeCertificateDetail", params)
- if err != nil {
- return nil, errors.Wrap(err, "DescribeCertificateDetail")
- }
- cert := &SCertificate{client: self}
- err = resp.Unmarshal(cert)
- if err != nil {
- return nil, errors.Wrap(err, "Unmarshal")
- }
- return cert, nil
- }
- // https://cloud.tencent.com/document/product/400/41665
- // 返回证书ID
- func (self *SQcloudClient) CreateCertificate(projectId, publicKey, privateKey, certType, desc string) (string, error) {
- params := map[string]string{
- "CertificatePublicKey": publicKey,
- "CertificateType": certType,
- "Alias": desc,
- }
- if len(privateKey) > 0 {
- params["CertificatePrivateKey"] = privateKey
- } else {
- if certType == "SVR" {
- return "", fmt.Errorf("certificate private key required while certificate type is SVR")
- }
- }
- if len(projectId) > 0 {
- params["ProjectId"] = projectId
- }
- resp, err := self.sslRequest("UploadCertificate", params)
- if err != nil {
- return "", err
- }
- return resp.GetString("CertificateId")
- }
- // https://cloud.tencent.com/document/product/400/41675
- func (self *SQcloudClient) DeleteCertificate(id string) error {
- if len(id) == 0 {
- return fmt.Errorf("DelteCertificate certificate id should not be empty")
- }
- params := map[string]string{"CertificateId": id}
- resp, err := self.sslRequest("DeleteCertificate", params)
- if err != nil {
- return errors.Wrap(err, "DeleteCertificate")
- }
- if deleted, _ := resp.Bool("DeleteResult"); deleted {
- return nil
- }
- return fmt.Errorf("DeleteCertificate %s", resp)
- }
- func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
- if self.Region != QCLOUD_DEFAULT_REGION {
- return []cloudprovider.ICloudLoadbalancerCertificate{}, nil
- }
- certs, err := self.client.GetCertificates("", "", "")
- if err != nil {
- return nil, errors.Wrap(err, "GetCertificates")
- }
- icerts := make([]cloudprovider.ICloudLoadbalancerCertificate, len(certs))
- for i := range certs {
- certs[i].client = self.client
- icerts[i] = &certs[i]
- }
- return icerts, nil
- }
- func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
- cert, err := self.client.GetCertificate(certId)
- if err != nil {
- return nil, errors.Wrap(err, "GetCertificate")
- }
- return cert, nil
- }
- // todo:目前onecloud端只能指定服务器端证书。需要兼容客户端证书?
- // todo:支持指定Project。
- // todo: 已过期的证书不能上传也不能关联资源
- func (self *SRegion) CreateILoadBalancerCertificate(input *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
- certId, err := self.client.CreateCertificate("", input.Certificate, input.PrivateKey, "SVR", input.Name)
- if err != nil {
- return nil, err
- }
- cert, err := self.client.GetCertificate(certId)
- if err != nil {
- return nil, errors.Wrapf(err, "GetCertificate")
- }
- return cert, nil
- }
- func (self *SQcloudClient) GetCertificates(projectId, certificateStatus, searchKey string) ([]SCertificate, error) {
- params := map[string]string{}
- params["Limit"] = "100"
- if len(projectId) > 0 {
- params["ProjectId"] = projectId
- }
- if len(certificateStatus) > 0 {
- params["CertificateStatus.0"] = certificateStatus
- }
- if len(searchKey) > 0 {
- params["SearchKey"] = searchKey
- }
- certs := []SCertificate{}
- offset := 0
- total := 100
- for total > offset {
- params["Offset"] = strconv.Itoa(offset)
- resp, err := self.sslRequest("DescribeCertificates", params)
- if err != nil {
- return nil, errors.Wrap(err, "DescribeCertificates")
- }
- _certs := []SCertificate{}
- err = resp.Unmarshal(&certs, "Certificates")
- if err != nil {
- return nil, errors.Wrap(err, "Unmarshal.Certificates")
- }
- err = resp.Unmarshal(&total, "TotalCount")
- if err != nil {
- return nil, errors.Wrap(err, "Unmarshal.TotalCount")
- }
- for i := range _certs {
- _certs[i].client = self
- certs = append(certs, _certs[i])
- }
- offset += 100
- }
- return certs, nil
- }
|