github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/pkg/clients/release/sbom.go (about)

     1  /* SBOM of type structures matches Pyxis structure
     2  
     3  When SBOM components are uploaded to Pyxis, key names have to be modified
     4  to conform to GraphQL naming conventions.
     5  1. Use _ instead of camel case, e.g. camelCase -> camel_case
     6  2. Use _ instead of -, e.g. key-with-dash -> key_with_dash
     7  See https://github.com/redhat-appstudio/release-service-utils/blob/main/pyxis/upload_sbom.py
     8  
     9  */
    10  
    11  package release
    12  
    13  import (
    14  	"crypto/tls"
    15  	"fmt"
    16  	"io"
    17  	"net/http"
    18  	"regexp"
    19  )
    20  
    21  // Defines a struct Links with fields for various types of links including artifacts, requests, RPM manifests,
    22  // test results, and vulnerabilities. Each field is represented by a corresponding struct type.
    23  type Links struct {
    24  	Artifacts       ArtifactLinks        `json:"artifacts"`
    25  	Requests        RequestLinks         `json:"requests"`
    26  	RpmManifest     RpmManifestLinks     `json:"rpm_manifest"`
    27  	TestResults     TestResultsLinks     `json:"test_results"`
    28  	Vulnerabilities VulnerabilitiesLinks `json:"vulnerabilities"`
    29  }
    30  
    31  // Defines a struct ArtifactLinks with a single field Href for storing a link related to an artifact.
    32  type ArtifactLinks struct {
    33  	Href string `json:"href"`
    34  }
    35  
    36  // Defines a struct RequestLinks with a single field Href for storing a link related to a request.
    37  type RequestLinks struct {
    38  	Href string `json:"href"`
    39  }
    40  
    41  // Defines a struct RpmManifestLinks with a single field Href for storing a link to an RPM manifest.
    42  type RpmManifestLinks struct {
    43  	Href string `json:"href"`
    44  }
    45  
    46  // Defines a struct TestResultsLinks with a single field Href for storing a link to test results.
    47  type TestResultsLinks struct {
    48  	Href string `json:"href"`
    49  }
    50  
    51  // Defines a struct VulnerabilitiesLinks with a single field Href for storing a link.
    52  type VulnerabilitiesLinks struct {
    53  	Href string `json:"href"`
    54  }
    55  
    56  // ContentManifest id of content manifest
    57  type ContentManifest struct {
    58  	ID string `json:"_id"`
    59  }
    60  
    61  // Defines a struct FreshnessGrade with fields for creation date, grade, and start date.
    62  type FreshnessGrade struct {
    63  	CreationDate string `json:"creation_date"`
    64  	Grade        string `json:"grade"`
    65  	StartDate    string `json:"start_date"`
    66  }
    67  
    68  // ParsedData general details of env
    69  type ParsedData struct {
    70  	Architecture  string   `json:"architecture"`
    71  	DockerVersion string   `json:"docker_version"`
    72  	EnvVariables  []string `json:"env_variables"`
    73  }
    74  
    75  // Defines a struct Image with various fields representing image properties and metadata.
    76  // It includes fields for ID, links, architecture, certification status, content manifest,
    77  // content manifest components, creator information, creation date, Docker image digest,
    78  // freshness grades, image ID, last update date, last updated by, object type, and parsed data.
    79  type Image struct {
    80  	ID                string           `json:"_id"`
    81  	Links             Links            `json:"_links"`
    82  	Architecture      string           `json:"architecture"`
    83  	Certified         bool             `json:"certified"`
    84  	ContentManifest   ContentManifest  `json:"content_manifest"`
    85  	CreatedBy         string           `json:"created_by"`
    86  	CreatedOnBehalfOf interface{}      `json:"created_on_behalf_of"`
    87  	CreationDate      string           `json:"creation_date"`
    88  	DockerImageDigest string           `json:"docker_image_digest"`
    89  	FreshnessGrades   []FreshnessGrade `json:"freshness_grades"`
    90  	ImageID           string           `json:"image_id"`
    91  	LastUpdateDate    string           `json:"last_update_date"`
    92  	LastUpdatedBy     string           `json:"last_updated_by"`
    93  	ObjectType        string           `json:"object_type"`
    94  	ParsedData        ParsedData       `json:"parsed_data"`
    95  }
    96  
    97  // GetPyxisImageByImageID makes a GET request to stage Pyxis to get an image
    98  // and returns it.
    99  func (r *ReleaseController) GetPyxisImageByImageID(pyxisStageImagesApiEndpoint, imageID string,
   100  	pyxisCertDecoded, pyxisKeyDecoded []byte) ([]byte, error) {
   101  
   102  	url := fmt.Sprintf("%s%s", pyxisStageImagesApiEndpoint, imageID)
   103  
   104  	// Create a TLS configuration with the key and certificate
   105  	cert, err := tls.X509KeyPair(pyxisCertDecoded, pyxisKeyDecoded)
   106  	if err != nil {
   107  		return nil, fmt.Errorf("error creating TLS certificate and key: %s", err)
   108  	}
   109  
   110  	// Create a client with the custom TLS configuration
   111  	client := &http.Client{
   112  		Transport: &http.Transport{
   113  			TLSClientConfig: &tls.Config{
   114  				Certificates: []tls.Certificate{cert},
   115  			},
   116  		},
   117  	}
   118  
   119  	// Send GET request
   120  	request, err := http.NewRequest("GET", url, nil)
   121  	if err != nil {
   122  		return nil, fmt.Errorf("error creating GET request: %s", err)
   123  	}
   124  
   125  	response, err := client.Do(request)
   126  	if err != nil {
   127  		return nil, fmt.Errorf("error sending GET request: %s", err)
   128  	}
   129  
   130  	defer response.Body.Close()
   131  
   132  	// Read the response body
   133  	body, err := io.ReadAll(response.Body)
   134  	if err != nil {
   135  		return nil, fmt.Errorf("error reading response body: %s", err)
   136  	}
   137  	return body, nil
   138  }
   139  
   140  // GetPyxisImageIDsFromCreatePyxisImageTaskLogs takes a slice of task logs (as this is what
   141  // TektonController.GetTaskRunLogs returns) and parses them for the imageIDs, returning them
   142  // as a slice.
   143  func (r *ReleaseController) GetPyxisImageIDsFromCreatePyxisImageTaskLogs(logs map[string]string) ([]string, error) {
   144  	var imageIDs []string
   145  
   146  	re := regexp.MustCompile(`(?:The image id is: )(.+)`)
   147  
   148  	for _, tasklog := range logs {
   149  		for _, matchingString := range re.FindAllString(tasklog, -1) {
   150  			imageIDs = append(imageIDs, re.FindStringSubmatch(matchingString)[1])
   151  		}
   152  	}
   153  
   154  	return imageIDs, nil
   155  }