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 }