yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/qcloud/certificate.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package qcloud
    16  
    17  import (
    18  	"crypto/sha1"
    19  	"fmt"
    20  	"strconv"
    21  	"strings"
    22  	"time"
    23  
    24  	"yunion.io/x/jsonutils"
    25  	"yunion.io/x/pkg/errors"
    26  
    27  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    28  	"yunion.io/x/cloudmux/pkg/multicloud"
    29  )
    30  
    31  type projectInfo struct {
    32  	ProjectID  string `json:"projectId"`
    33  	OwnerUin   int64  `json:"ownerUin"`
    34  	Name       string `json:"name"`
    35  	CreatorUin int64  `json:"creatorUin"`
    36  	CreateTime string `json:"createTime"`
    37  	Info       string `json:"info"`
    38  }
    39  
    40  // https://cloud.tencent.com/document/api/400/13675
    41  type SCertificate struct {
    42  	multicloud.SResourceBase
    43  	QcloudTags
    44  	region *SRegion
    45  
    46  	CertificateID       string      `json:"CertificateId"`
    47  	CertificateType     string      `json:"CertificateType"`
    48  	Deployable          bool        `json:"Deployable"`
    49  	RenewAble           bool        `json:"RenewAble"`
    50  	OwnerUin            string      `json:"ownerUin"`
    51  	ProjectID           string      `json:"projectId"`
    52  	From                string      `json:"from"`
    53  	ProductZhName       string      `json:"productZhName"`
    54  	Domain              string      `json:"domain"`
    55  	Alias               string      `json:"alias"`
    56  	Status              int         `json:"status"`
    57  	VulnerabilityStatus string      `json:"vulnerability_status"`
    58  	CERTBeginTime       time.Time   `json:"certBeginTime"`
    59  	CERTEndTime         time.Time   `json:"certEndTime"`
    60  	ValidityPeriod      string      `json:"validityPeriod"`
    61  	InsertTime          string      `json:"insertTime"`
    62  	ProjectInfo         projectInfo `json:"projectInfo"`
    63  	StatusName          string      `json:"status_name"`
    64  	IsVip               bool        `json:"is_vip"`
    65  	IsDv                bool        `json:"is_dv"`
    66  	IsWildcard          bool        `json:"is_wildcard"`
    67  	IsVulnerability     bool        `json:"is_vulnerability"`
    68  
    69  	// certificate details
    70  	detailsInitd          bool     `json:"details_initd"`
    71  	SubjectAltName        []string `json:"subjectAltName"`
    72  	CertificatePrivateKey string   `json:"CertificatePrivateKey"`
    73  	CertificatePublicKey  string   `json:"CertificatePublicKey"`
    74  }
    75  
    76  func (self *SCertificate) GetDetails() (*SCertificate, error) {
    77  	if !self.detailsInitd {
    78  		cert, err := self.region.GetCertificate(self.GetId())
    79  		if err != nil {
    80  			return nil, err
    81  		}
    82  		self.detailsInitd = true
    83  		self.SubjectAltName = cert.SubjectAltName
    84  		self.CertificatePrivateKey = cert.CertificatePrivateKey
    85  		self.CertificatePublicKey = cert.CertificatePublicKey
    86  	}
    87  	return self, nil
    88  }
    89  
    90  func (self *SCertificate) GetPublickKey() string {
    91  	self.GetDetails()
    92  	return self.CertificatePublicKey
    93  }
    94  
    95  func (self *SCertificate) GetPrivateKey() string {
    96  	self.GetDetails()
    97  	return self.CertificatePrivateKey
    98  }
    99  
   100  // 证书不能修改
   101  func (self *SCertificate) Sync(name, privateKey, publickKey string) error {
   102  	return cloudprovider.ErrNotSupported
   103  }
   104  
   105  func (self *SCertificate) Delete() error {
   106  	return self.region.DeleteCertificate(self.GetId())
   107  }
   108  
   109  func (self *SCertificate) GetId() string {
   110  	return self.CertificateID
   111  }
   112  
   113  func (self *SCertificate) GetName() string {
   114  	return self.Alias
   115  }
   116  
   117  func (self *SCertificate) GetGlobalId() string {
   118  	return self.CertificateID
   119  }
   120  
   121  // todo: 貌似目前onecloud没有记录状态
   122  func (self *SCertificate) GetStatus() string {
   123  	return strconv.Itoa(self.Status)
   124  }
   125  
   126  func (self *SCertificate) Refresh() error {
   127  	cert, err := self.region.GetCertificate(self.GetId())
   128  	if err != nil {
   129  		return errors.Wrap(err, "GetCertificate")
   130  	}
   131  
   132  	return jsonutils.Update(self, cert)
   133  }
   134  
   135  func (self *SCertificate) IsEmulated() bool {
   136  	return false
   137  }
   138  
   139  func (self *SCertificate) GetCommonName() string {
   140  	return self.Domain
   141  }
   142  
   143  func (self *SCertificate) GetSubjectAlternativeNames() string {
   144  	self.GetDetails()
   145  	return strings.Join(self.SubjectAltName, ",")
   146  }
   147  
   148  func (self *SCertificate) GetFingerprint() string {
   149  	self.GetDetails()
   150  	_fp := sha1.Sum([]byte(self.CertificatePublicKey))
   151  	fp := fmt.Sprintf("sha1:% x", _fp)
   152  	return strings.Replace(fp, " ", ":", -1)
   153  }
   154  
   155  func (self *SCertificate) GetExpireTime() time.Time {
   156  	return self.CERTEndTime
   157  }
   158  
   159  func (self *SCertificate) GetProjectId() string {
   160  	return self.ProjectID
   161  }
   162  
   163  // ssl.tencentcloudapi.com
   164  /*
   165  状态值 0:审核中,1:已通过,2:审核失败,3:已过期,4:已添加 DNS 解析记录,5:OV/EV 证书,待提交资料,6:订单取消中,7:已取消,8:已提交资料, 待上传确认函。
   166  */
   167  func (self *SRegion) GetCertificates(projectId, certificateStatus, searchKey string) ([]SCertificate, error) {
   168  	params := map[string]string{}
   169  	params["Limit"] = "100"
   170  	if len(projectId) > 0 {
   171  		params["ProjectId"] = projectId
   172  	}
   173  
   174  	if len(certificateStatus) > 0 {
   175  		params["CertificateStatus.0"] = certificateStatus
   176  	}
   177  
   178  	if len(searchKey) > 0 {
   179  		params["SearchKey"] = searchKey
   180  	}
   181  
   182  	certs := []SCertificate{}
   183  	offset := 0
   184  	total := 100
   185  	for total > offset {
   186  		params["Offset"] = strconv.Itoa(offset)
   187  		resp, err := self.sslRequest("DescribeCertificates", params)
   188  		if err != nil {
   189  			return nil, errors.Wrap(err, "DescribeCertificates")
   190  		}
   191  
   192  		_certs := []SCertificate{}
   193  		err = resp.Unmarshal(&certs, "Certificates")
   194  		if err != nil {
   195  			return nil, errors.Wrap(err, "Unmarshal.Certificates")
   196  		}
   197  
   198  		err = resp.Unmarshal(&total, "TotalCount")
   199  		if err != nil {
   200  			return nil, errors.Wrap(err, "Unmarshal.TotalCount")
   201  		}
   202  
   203  		certs = append(certs, _certs...)
   204  		offset += 100
   205  	}
   206  
   207  	for i := range certs {
   208  		certs[i].region = self
   209  	}
   210  
   211  	return certs, nil
   212  }
   213  
   214  // https://cloud.tencent.com/document/product/400/41674
   215  func (self *SRegion) GetCertificate(certId string) (*SCertificate, error) {
   216  	params := map[string]string{
   217  		"CertificateId": certId,
   218  	}
   219  
   220  	resp, err := self.sslRequest("DescribeCertificateDetail", params)
   221  	if err != nil {
   222  		return nil, errors.Wrap(err, "DescribeCertificateDetail")
   223  	}
   224  
   225  	cert := &SCertificate{}
   226  	err = resp.Unmarshal(cert)
   227  	if err != nil {
   228  		return nil, errors.Wrap(err, "Unmarshal")
   229  	}
   230  	cert.region = self
   231  
   232  	return cert, nil
   233  }
   234  
   235  // https://cloud.tencent.com/document/product/400/41665
   236  // 返回证书ID
   237  func (self *SRegion) CreateCertificate(projectId, publicKey, privateKey, certType, desc string) (string, error) {
   238  	params := map[string]string{
   239  		"CertificatePublicKey": publicKey,
   240  		"CertificateType":      certType,
   241  		"Alias":                desc,
   242  	}
   243  
   244  	if len(privateKey) > 0 {
   245  		params["CertificatePrivateKey"] = privateKey
   246  	} else {
   247  		if certType == "SVR" {
   248  			return "", fmt.Errorf("certificate private key required while certificate type is SVR")
   249  		}
   250  	}
   251  
   252  	if len(projectId) > 0 {
   253  		params["ProjectId"] = projectId
   254  	}
   255  
   256  	resp, err := self.sslRequest("UploadCertificate", params)
   257  	if err != nil {
   258  		return "", err
   259  	}
   260  
   261  	return resp.GetString("CertificateId")
   262  }
   263  
   264  // https://cloud.tencent.com/document/product/400/41675
   265  func (self *SRegion) DeleteCertificate(id string) error {
   266  	if len(id) == 0 {
   267  		return fmt.Errorf("DelteCertificate certificate id should not be empty")
   268  	}
   269  
   270  	params := map[string]string{"CertificateId": id}
   271  	resp, err := self.sslRequest("DeleteCertificate", params)
   272  	if err != nil {
   273  		return errors.Wrap(err, "DeleteCertificate")
   274  	}
   275  
   276  	if deleted, _ := resp.Bool("DeleteResult"); deleted {
   277  		return nil
   278  	} else {
   279  		return fmt.Errorf("DeleteCertificate %s", resp)
   280  	}
   281  }