github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/certificate_management.go (about) 1 /* 2 * Copyright 2021 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. 3 */ 4 5 package govcd 6 7 import ( 8 "fmt" 9 "github.com/vmware/go-vcloud-director/v2/types/v56" 10 "net/url" 11 ) 12 13 // Certificate is a structure defining a certificate in VCD 14 // It is called "Certificate Library" in the UI, and "Certificate Library item" in the API 15 type Certificate struct { 16 CertificateLibrary *types.CertificateLibraryItem 17 Href string 18 client *Client 19 } 20 21 // GetCertificateFromLibraryById Returns certificate from library of certificates 22 func getCertificateFromLibraryById(client *Client, id string, additionalHeader map[string]string) (*Certificate, error) { 23 endpoint, err := getEndpointByVersion(client) 24 if err != nil { 25 return nil, err 26 } 27 minimumApiVersion, err := client.checkOpenApiEndpointCompatibility(endpoint) 28 if err != nil { 29 return nil, err 30 } 31 32 if id == "" { 33 return nil, fmt.Errorf("empty certificate ID") 34 } 35 36 urlRef, err := client.OpenApiBuildEndpoint(endpoint, id) 37 if err != nil { 38 return nil, err 39 } 40 41 certificate := &Certificate{ 42 CertificateLibrary: &types.CertificateLibraryItem{}, 43 client: client, 44 Href: urlRef.String(), 45 } 46 47 err = client.OpenApiGetItem(minimumApiVersion, urlRef, nil, certificate.CertificateLibrary, additionalHeader) 48 if err != nil { 49 return nil, err 50 } 51 52 return certificate, nil 53 } 54 55 func getEndpointByVersion(client *Client) (string, error) { 56 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibrary 57 newerApiVersion, err := client.VersionEqualOrGreater("10.3", 3) 58 if err != nil { 59 return "", err 60 } 61 if !newerApiVersion { 62 // in previous version exist only API with mistype in name 63 endpoint = types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibraryOld 64 } 65 return endpoint, err 66 } 67 68 // GetCertificateFromLibraryById Returns certificate from library of certificates from System Context 69 func (client *Client) GetCertificateFromLibraryById(id string) (*Certificate, error) { 70 return getCertificateFromLibraryById(client, id, nil) 71 } 72 73 // GetCertificateFromLibraryById Returns certificate from library of certificates from Org context 74 func (adminOrg *AdminOrg) GetCertificateFromLibraryById(id string) (*Certificate, error) { 75 tenantContext, err := adminOrg.getTenantContext() 76 if err != nil { 77 return nil, err 78 } 79 return getCertificateFromLibraryById(adminOrg.client, id, getTenantContextHeader(tenantContext)) 80 } 81 82 // addCertificateToLibrary uploads certificates with configuration details 83 func addCertificateToLibrary(client *Client, certificateConfig *types.CertificateLibraryItem, 84 additionalHeader map[string]string) (*Certificate, error) { 85 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibrary 86 apiVersion, err := client.checkOpenApiEndpointCompatibility(endpoint) 87 if err != nil { 88 return nil, err 89 } 90 91 urlRef, err := client.OpenApiBuildEndpoint(endpoint) 92 if err != nil { 93 return nil, err 94 } 95 96 typeResponse := &Certificate{ 97 CertificateLibrary: &types.CertificateLibraryItem{}, 98 client: client, 99 Href: urlRef.String(), 100 } 101 102 err = client.OpenApiPostItem(apiVersion, urlRef, nil, 103 certificateConfig, typeResponse.CertificateLibrary, additionalHeader) 104 if err != nil { 105 return nil, err 106 } 107 108 return typeResponse, nil 109 } 110 111 // AddCertificateToLibrary uploads certificates with configuration details 112 func (adminOrg *AdminOrg) AddCertificateToLibrary(certificateConfig *types.CertificateLibraryItem) (*Certificate, error) { 113 tenantContext, err := adminOrg.getTenantContext() 114 if err != nil { 115 return nil, err 116 } 117 return addCertificateToLibrary(adminOrg.client, certificateConfig, getTenantContextHeader(tenantContext)) 118 } 119 120 // AddCertificateToLibrary uploads certificates with configuration details 121 func (client *Client) AddCertificateToLibrary(certificateConfig *types.CertificateLibraryItem) (*Certificate, error) { 122 return addCertificateToLibrary(client, certificateConfig, nil) 123 } 124 125 // getAllCertificateFromLibrary retrieves all certificates. Query parameters can be supplied to perform additional 126 // filtering 127 func getAllCertificateFromLibrary(client *Client, queryParameters url.Values, additionalHeader map[string]string) ([]*Certificate, error) { 128 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibrary 129 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 130 if err != nil { 131 return nil, err 132 } 133 134 urlRef, err := client.OpenApiBuildEndpoint(endpoint) 135 if err != nil { 136 return nil, err 137 } 138 139 responses := []*types.CertificateLibraryItem{{}} 140 err = client.OpenApiGetAllItems(apiVersion, urlRef, queryParameters, &responses, additionalHeader) 141 if err != nil { 142 return nil, err 143 } 144 145 var wrappedCertificates []*Certificate 146 for _, response := range responses { 147 urlRef, err := client.OpenApiBuildEndpoint(endpoint, response.Id) 148 if err != nil { 149 return nil, err 150 } 151 wrappedCertificate := &Certificate{ 152 CertificateLibrary: response, 153 client: client, 154 Href: urlRef.String(), 155 } 156 wrappedCertificates = append(wrappedCertificates, wrappedCertificate) 157 } 158 159 return wrappedCertificates, nil 160 } 161 162 // GetAllCertificatesFromLibrary retrieves all available certificates from certificate library. 163 // Query parameters can be supplied to perform additional filtering 164 func (client *Client) GetAllCertificatesFromLibrary(queryParameters url.Values) ([]*Certificate, error) { 165 return getAllCertificateFromLibrary(client, queryParameters, nil) 166 } 167 168 // GetAllCertificatesFromLibrary r retrieves all available certificates from certificate library. 169 // Query parameters can be supplied to perform additional filtering 170 func (adminOrg *AdminOrg) GetAllCertificatesFromLibrary(queryParameters url.Values) ([]*Certificate, error) { 171 tenantContext, err := adminOrg.getTenantContext() 172 if err != nil { 173 return nil, err 174 } 175 return getAllCertificateFromLibrary(adminOrg.client, queryParameters, getTenantContextHeader(tenantContext)) 176 } 177 178 // getCertificateFromLibraryByName retrieves certificate from certificate library by given name 179 // When the alias contains commas, semicolons or asterisks, the encoding is rejected by the API in VCD. 180 // For this reason, when one or more commas, semicolons or asterisks are present we run the search brute force, 181 // by fetching all certificates and comparing the alias. 182 // Also, url.QueryEscape as well as url.Values.Encode() both encode the space as a + character. So we use 183 // search brute force too. Reference to issue: 184 // https://github.com/golang/go/issues/4013 185 // https://github.com/czos/goamz/pull/11/files 186 func getCertificateFromLibraryByName(client *Client, name string, additionalHeader map[string]string) (*Certificate, error) { 187 slowSearch, params := shouldDoSlowSearch("alias", name) 188 189 var foundCertificates []*Certificate 190 certificates, err := getAllCertificateFromLibrary(client, params, additionalHeader) 191 if err != nil { 192 return nil, err 193 } 194 if len(certificates) == 0 { 195 return nil, ErrorEntityNotFound 196 } 197 foundCertificates = append(foundCertificates, certificates[0]) 198 199 if slowSearch { 200 foundCertificates = nil 201 for _, certificate := range certificates { 202 if certificate.CertificateLibrary.Alias == name { 203 foundCertificates = append(foundCertificates, certificate) 204 } 205 } 206 if len(foundCertificates) == 0 { 207 return nil, ErrorEntityNotFound 208 } 209 if len(foundCertificates) > 1 { 210 return nil, fmt.Errorf("more than one certificate found with name '%s'", name) 211 } 212 } 213 214 if len(certificates) > 1 && !slowSearch { 215 { 216 return nil, fmt.Errorf("more than one certificate found with name '%s'", name) 217 } 218 } 219 return foundCertificates[0], nil 220 } 221 222 // GetCertificateFromLibraryByName retrieves certificate from certificate library by given name 223 func (client *Client) GetCertificateFromLibraryByName(name string) (*Certificate, error) { 224 return getCertificateFromLibraryByName(client, name, nil) 225 } 226 227 // GetCertificateFromLibraryByName retrieves certificate from certificate library by given name 228 func (adminOrg *AdminOrg) GetCertificateFromLibraryByName(name string) (*Certificate, error) { 229 tenantContext, err := adminOrg.getTenantContext() 230 if err != nil { 231 return nil, err 232 } 233 return getCertificateFromLibraryByName(adminOrg.client, name, getTenantContextHeader(tenantContext)) 234 } 235 236 // Update updates existing Certificate. Allows changing only alias and description 237 func (certificate *Certificate) Update() (*Certificate, error) { 238 endpoint, err := getEndpointByVersion(certificate.client) 239 if err != nil { 240 return nil, err 241 } 242 minimumApiVersion, err := certificate.client.checkOpenApiEndpointCompatibility(endpoint) 243 if err != nil { 244 return nil, err 245 } 246 247 if certificate.CertificateLibrary.Id == "" { 248 return nil, fmt.Errorf("cannot update certificate without id") 249 } 250 251 urlRef, err := certificate.client.OpenApiBuildEndpoint(endpoint, certificate.CertificateLibrary.Id) 252 if err != nil { 253 return nil, err 254 } 255 256 returnCertificate := &Certificate{ 257 CertificateLibrary: &types.CertificateLibraryItem{}, 258 client: certificate.client, 259 } 260 261 err = certificate.client.OpenApiPutItem(minimumApiVersion, urlRef, nil, certificate.CertificateLibrary, 262 returnCertificate.CertificateLibrary, nil) 263 if err != nil { 264 return nil, fmt.Errorf("error updating certificate: %s", err) 265 } 266 267 return returnCertificate, nil 268 } 269 270 // Delete deletes certificate from Certificate library 271 func (certificate *Certificate) Delete() error { 272 endpoint, err := getEndpointByVersion(certificate.client) 273 if err != nil { 274 return err 275 } 276 minimumApiVersion, err := certificate.client.checkOpenApiEndpointCompatibility(endpoint) 277 if err != nil { 278 return err 279 } 280 281 if certificate.CertificateLibrary.Id == "" { 282 return fmt.Errorf("cannot delete certificate without id") 283 } 284 285 urlRef, err := certificate.client.OpenApiBuildEndpoint(endpoint, certificate.CertificateLibrary.Id) 286 if err != nil { 287 return err 288 } 289 290 err = certificate.client.OpenApiDeleteItem(minimumApiVersion, urlRef, nil, nil) 291 292 if err != nil { 293 return fmt.Errorf("error deleting certificate: %s", err) 294 } 295 296 return nil 297 }