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  }