1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-09-16 09:26:22 +02:00

Added user API key authentication method (#3748)

* changes to detectExec before master merge

* changes for detectExecuteScan

* self generated code added

* fix syntax errors and update docu

* added unit tests for fail and Group

* fix failOn bug

* add Groups as string array

* add Groups as string array

* tests and validation for groups, failOn

* Updated docs and added more tests

* documentation md files should not be changed

* Handle merge conflicts from PR 1845

* fix merge errors

* remove duplicate groups, merge error

* adding buildCode and buildTool as params

* switching build options

* building maven modules

* parameter correction

* parameter correction

* gnerate with new build parameter

* adding comments

* removing piper lib master and modifying goUtils to download 1.5.7 release

* first cleaning then installing

* multi module maven built

* multi module maven built removing unwanted code

* multi module maven built moving inside switch

* testing

* modifying the default use case to also call maven build

* modifying the default use case to also call maven build wih --

* corrected maven build command

* corrected maven build command with %v

* skipping test runs

* testing for MTA project with single pom

* adding absolute path to m2 path

* clean up

* adding switch for mta and maven and removing env from containers

* commiting changes for new detect step

* correting log message

* code clean up

* unit tests changes to detectExecute

* basic tests for new change

* restoring piperGoUtils to download correct piper binary

* code clean up

* code clean up

* protecodeExecuteScan -> Added authentication with user API key

* protecodeExecuteScan -> updating .yml file

* protecodeExecuteScan -> go generate fixed

* protecodeExecuteScan -> naming convention applied for UserAPIKey parameter

* protecodeExecuteScan -> extending groovy code for mapping jenkins credentials

Co-authored-by: D072410 <giridhar.shenoy@sap.com>
Co-authored-by: Keshav <anil.keshav@sap.com>
Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
This commit is contained in:
Umidjon Urunov
2022-10-10 10:55:21 +02:00
committed by GitHub
parent e8ba1b043d
commit e9707e7638
7 changed files with 83 additions and 70 deletions

View File

@@ -100,7 +100,7 @@ func runProtecodeScan(config *protecodeExecuteScanOptions, influx *protecodeExec
} else if len(config.FetchURL) > 0 {
// Get filename from a fetch URL
fileName = filepath.Base(config.FetchURL)
log.Entry().Debugf("[DEBUG] ===> Filepath from fetch URL: %v", fileName)
log.Entry().Debugf("[DEBUG] ===> Filename from fetch URL: %v", fileName)
}
log.Entry().Debug("Execute protecode scan")
@@ -156,12 +156,10 @@ func executeProtecodeScan(influx *protecodeExecuteScanInflux, client protecode.P
if config.ReplaceProductID > 0 {
log.Entry().Infof("replaceProductID has been provided (%v) and checking ...", config.ReplaceProductID)
// log.Entry().Debugf("[DEBUG] ===> ReplaceProductID has been provided and required to verify it: %v", config.ReplaceProductID)
// Validate provided product id, if not valid id then throw an error
if client.VerifyProductID(config.ReplaceProductID) {
log.Entry().Infof("replaceProductID has been checked and it's valid")
// log.Entry().Debugf("[DEBUG] ===> ReplaceProductID exists")
productID = config.ReplaceProductID
} else {
log.Entry().Debugf("[DEBUG] ===> ReplaceProductID doesn't exist")
@@ -171,12 +169,10 @@ func executeProtecodeScan(influx *protecodeExecuteScanInflux, client protecode.P
} else {
// Get existing product id by filename
log.Entry().Infof("replaceProductID is not provided and automatic search starts from group: %v ... ", config.Group)
// log.Entry().Debugf("[DEBUG] ===> ReplaceProductID hasn't provided and automatic search starts... ")
productID = client.LoadExistingProduct(config.Group, fileName)
if productID > 0 {
log.Entry().Infof("Automatic search completed and found following product id: %v", productID)
// log.Entry().Debugf("[DEBUG] ===> Returned productID: %v", productID)
} else {
log.Entry().Infof("Automatic search completed but not found any similar product scan, now starts new scan creation")
}
@@ -185,8 +181,6 @@ func executeProtecodeScan(influx *protecodeExecuteScanInflux, client protecode.P
// check if no existing is found
productID = uploadScanOrDeclareFetch(utils, *config, productID, client, fileName)
log.Entry().Debugf("[DEBUG] ===> After 'uploadScanOrDeclareFetch' returned productID: %v", productID)
if productID <= 0 {
return fmt.Errorf("the product id is not valid '%d'", productID)
}
@@ -311,11 +305,12 @@ func createProtecodeClient(config *protecodeExecuteScanOptions) protecode.Protec
pc := protecode.Protecode{}
protecodeOptions := protecode.Options{
ServerURL: config.ServerURL,
Logger: log.Entry().WithField("package", "SAP/jenkins-library/pkg/protecode"),
Duration: duration,
Username: config.Username,
Password: config.Password,
ServerURL: config.ServerURL,
Logger: log.Entry().WithField("package", "SAP/jenkins-library/pkg/protecode"),
Duration: duration,
Username: config.Username,
Password: config.Password,
UserAPIKey: config.UserAPIKey,
}
pc.SetOptions(protecodeOptions)
@@ -324,34 +319,25 @@ func createProtecodeClient(config *protecodeExecuteScanOptions) protecode.Protec
}
func uploadScanOrDeclareFetch(utils protecodeUtils, config protecodeExecuteScanOptions, productID int, client protecode.Protecode, fileName string) int {
//check if the LoadExistingProduct) before returns an valid product id, than skip this
//if !hasExisting(productID, config.VerifyOnly) {
log.Entry().Debugf("[DEBUG] ===> In uploadScanOrDeclareFetch: %v", productID)
// check if product doesn't exist then create a new one.
if productID <= 0 {
log.Entry().Infof("New product creation started ... ")
// log.Entry().Debugf("[DEBUG] ===> New product creation started: %v", productID)
productID = uploadFile(utils, config, productID, client, fileName, false)
log.Entry().Infof("New product has been successfully created: %v", productID)
// log.Entry().Debugf("[DEBUG] ===> After uploading [productID < 0] file returned productID: %v", productID)
return productID
// In case product already exists and "VerifyOnly (reuseExisting)" is false then we replace binary without creating a new product.
} else if (productID > 0) && !config.VerifyOnly {
log.Entry().Infof("Product already exists and 'VerifyOnly (reuseExisting)' is false then product (%v) binary and scan result will be replaced without creating a new product.", productID)
// log.Entry().Debugf("[DEBUG] ===> Replace binary entry point started %v", productID)
productID = uploadFile(utils, config, productID, client, fileName, true)
// log.Entry().Debugf("[DEBUG] ===> After uploading file [(productID > 0) && !config.VerifyOnly] returned productID: %v", productID)
return productID
// If product already exists and "reuseExisting" option is enabled then return the latest similar scan result.
} else {
log.Entry().Infof("VerifyOnly (reuseExisting) option is enabled and returned productID: %v", productID)
// log.Entry().Debugf("[DEBUG] ===> VerifyOnly (reuseExisting) option is enabled and returned productID: %v", productID)
return productID
}
}
@@ -382,7 +368,6 @@ func uploadFile(utils protecodeUtils, config protecodeExecuteScanOptions, produc
resultData := client.UploadScanFile(config.CleanupMode, config.Group, pathToFile, combinedFileName, version, productID, replaceBinary)
productID = resultData.Result.ProductID
log.Entry().Debugf("[DEBUG] ===> uploadFile return FINAL product id: %v", productID)
}
return productID
}

View File

@@ -38,6 +38,7 @@ type protecodeExecuteScanOptions struct {
ReplaceProductID int `json:"replaceProductId,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
UserAPIKey string `json:"userAPIKey,omitempty"`
Version string `json:"version,omitempty"`
CustomScanVersion string `json:"customScanVersion,omitempty"`
VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"`
@@ -174,6 +175,7 @@ BDBA (Protecode) uses a combination of static binary analysis techniques to X-ra
log.RegisterSecret(stepConfig.DockerConfigJSON)
log.RegisterSecret(stepConfig.Username)
log.RegisterSecret(stepConfig.Password)
log.RegisterSecret(stepConfig.UserAPIKey)
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
@@ -254,6 +256,7 @@ func addProtecodeExecuteScanFlags(cmd *cobra.Command, stepConfig *protecodeExecu
cmd.Flags().IntVar(&stepConfig.ReplaceProductID, "replaceProductId", 0, "Specify <replaceProductId> which application binary will be replaced and rescanned and product id remains unchanged. By using this parameter, Protecode avoids creating multiple same products. Note this will affect results and feeds. If product id is not specified, then Piper starts auto detection mechanism, more precisely it searches a product id with scanned product name in that specified group, if there are several scans have been done with the same product name then the latest scan id will be fetched from BDBA backend. After obtaining product id, Piper re-uploads / replaces new binary without affecting already existing product id.")
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User which is used for the protecode scan")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password which is used for the user")
cmd.Flags().StringVar(&stepConfig.UserAPIKey, "userAPIKey", os.Getenv("PIPER_userAPIKey"), "User API key which is used for API calls. Replacement for username and password / basic authentication.")
cmd.Flags().StringVar(&stepConfig.Version, "version", os.Getenv("PIPER_version"), "The version of the artifact to allow identification in protecode backend")
cmd.Flags().StringVar(&stepConfig.CustomScanVersion, "customScanVersion", os.Getenv("PIPER_customScanVersion"), "A custom version used along with the uploaded scan results.")
cmd.Flags().StringVar(&stepConfig.VersioningModel, "versioningModel", `major`, "The versioning model used for result reporting (based on the artifact version). Example 1.2.3 using `major` will result in version 1")
@@ -277,6 +280,7 @@ func protecodeExecuteScanMetadata() config.StepData {
Inputs: config.StepInputs{
Secrets: []config.StepSecrets{
{Name: "protecodeCredentialsId", Description: "Jenkins 'Username with password' credentials ID containing username and password to authenticate to the Protecode system.", Type: "jenkins"},
{Name: "protecodeApiKeyCredentialsId", Description: "Jenkins 'Secret text' credentials ID containing API Key/token to authenticate to BDBA server.", Type: "jenkins"},
{Name: "dockerConfigJsonCredentialsId", Description: "Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)). You can create it like explained in [Prerequisites](https://www.project-piper.io/steps/protecodeExecuteScan/#prerequisites).", Type: "jenkins", Aliases: []config.Alias{{Name: "dockerCredentialsId", Deprecated: true}}},
},
Parameters: []config.StepParameters{
@@ -474,6 +478,27 @@ func protecodeExecuteScanMetadata() config.StepData {
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_password"),
},
{
Name: "userAPIKey",
ResourceRef: []config.ResourceReference{
{
Name: "protecodeApiKeyCredentialsId",
Param: "userAPIKey",
Type: "secret",
},
{
Name: "protecodeApiKeyVaultSecretName",
Type: "vaultSecret",
Default: "protecode",
},
},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_userAPIKey"),
},
{
Name: "version",
ResourceRef: []config.ResourceReference{

View File

@@ -380,7 +380,12 @@ func handleAuthentication(req *http.Request, username, password, token string) {
// Handle authentication if not done already
if (len(username) > 0 || len(password) > 0) && len(req.Header.Get(authHeaderKey)) == 0 {
req.SetBasicAuth(username, password)
log.Entry().Debug("Using Basic Authentication ****/****")
log.Entry().Debug("Using Basic Authentication ****/****\n")
log.Entry().Warning("------------------")
log.Entry().Warning("*** [WARNING] *** : Basic authentication is used, recommended method is API key/token authentication")
log.Entry().Warning("*** [WARNING] *** : Basic authentication will be deprecated in the near future, please use API key/token authentication.")
log.Entry().Warning("*** [WARNING] *** : For more details, please refer to BDBA documentation.")
log.Entry().Warning("------------------\n")
}
if len(token) > 0 && len(req.Header.Get(authHeaderKey)) == 0 {
req.Header.Add(authHeaderKey, token)

View File

@@ -122,6 +122,7 @@ func TestSendRequest(t *testing.T) {
passedCookies := []*http.Cookie{}
var passedUsername string
var passedPassword string
// Start a local HTTP server
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
passedHeaders = map[string][]string{}
@@ -154,6 +155,7 @@ func TestSendRequest(t *testing.T) {
{client: Client{logger: log.Entry().WithField("package", "SAP/jenkins-library/pkg/http")}, method: "GET", header: map[string][]string{"Testheader": {"Test1", "Test2"}}, expected: "OK"},
{client: Client{logger: log.Entry().WithField("package", "SAP/jenkins-library/pkg/http")}, cookies: []*http.Cookie{{Name: "TestCookie1", Value: "TestValue1"}, {Name: "TestCookie2", Value: "TestValue2"}}, method: "GET", expected: "OK"},
{client: Client{logger: log.Entry().WithField("package", "SAP/jenkins-library/pkg/http"), username: "TestUser", password: "TestPwd"}, method: "GET", expected: "OK"},
{client: Client{logger: log.Entry().WithField("package", "SAP/jenkins-library/pkg/http"), token: "api-token-string"}, method: "GET", expected: "OK"},
}
for key, test := range tt {
@@ -191,6 +193,14 @@ func TestSendRequest(t *testing.T) {
assert.NotContains(t, log, fmt.Sprintf("Authorization:[Basic %s]", credentialsEncoded))
assert.Contains(t, log, "Authorization:[<set>]")
}
// Token authentication
if len(test.client.token) > 0 {
assert.Equal(t, test.client.token, "api-token-string")
log := fmt.Sprintf("%s", logBuffer)
assert.Contains(t, log, fmt.Sprintf("Using Token Authentication ****"))
assert.Contains(t, log, "Authorization:[<set>]")
}
})
}
}

View File

@@ -81,7 +81,7 @@ type Triage struct {
type User struct {
ID int `json:"id,omitempty"`
Email string `json:"email,omitempty"`
Girstname string `json:"firstname,omitempty"`
Firstname string `json:"firstname,omitempty"`
Lastname string `json:"lastname,omitempty"`
Username string `json:"username,omitempty"`
}
@@ -107,11 +107,12 @@ func makeProtecode(opts Options) Protecode {
//Options struct which can be used to configure the Protecode struct
type Options struct {
ServerURL string
Duration time.Duration
Username string
Password string
Logger *logrus.Entry
ServerURL string
Duration time.Duration
Username string
Password string
UserAPIKey string
Logger *logrus.Entry
}
//SetOptions setter function to set the internal properties of the protecode
@@ -126,7 +127,15 @@ func (pc *Protecode) SetOptions(options Options) {
pc.logger = log.Entry().WithField("package", "SAP/jenkins-library/pkg/protecode")
}
httpOptions := piperHttp.ClientOptions{MaxRequestDuration: options.Duration, Username: options.Username, Password: options.Password, Logger: options.Logger}
httpOptions := piperHttp.ClientOptions{MaxRequestDuration: options.Duration, Logger: options.Logger}
// If userAPIKey is not empty then we will use it for user authentication, instead of username & password
if options.UserAPIKey != "" {
httpOptions.Token = "Bearer " + options.UserAPIKey
} else {
httpOptions.Username = options.Username
httpOptions.Password = options.Password
}
pc.client.SetOptions(httpOptions)
}
@@ -321,28 +330,20 @@ func (pc *Protecode) LoadReport(reportFileName string, productID int) *io.ReadCl
// UploadScanFile upload the scan file to the protecode server
func (pc *Protecode) UploadScanFile(cleanupMode, group, filePath, fileName, version string, productID int, replaceBinary bool) *ResultData {
log.Entry().Debugf("[DEBUG] ===> UploadScanFile started.....")
deleteBinary := (cleanupMode == "binary" || cleanupMode == "complete")
var headers = make(map[string][]string)
if (replaceBinary) && (version != "") {
log.Entry().Debugf("[DEBUG] ===> replaceBinary && version != empty ")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Replace": {fmt.Sprintf("%v", productID)}, "Version": {version}}
} else if replaceBinary {
log.Entry().Debugf("[DEBUG] ===> replaceBinary")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Replace": {fmt.Sprintf("%v", productID)}}
} else if version != "" {
log.Entry().Debugf("[DEBUG] ===> version != empty ")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Version": {version}}
} else {
log.Entry().Debugf("[DEBUG] ===> replaceBinary is false and version == empty")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}}
}
// log.Entry().Debugf("[DEBUG] ===> Headers for UploadScanFile upload: %v", headers)
uploadURL := fmt.Sprintf("%v/api/upload/%v", pc.serverURL, fileName)
r, err := pc.client.UploadRequest(http.MethodPut, uploadURL, filePath, "file", headers, nil, "binary")
@@ -353,20 +354,15 @@ func (pc *Protecode) UploadScanFile(cleanupMode, group, filePath, fileName, vers
pc.logger.Info("Upload successful")
}
// log.Entry().Debugf("[DEBUG] ===> Upload request r: %v", r)
// log.Entry().Debugf("[DEBUG] ===> Upload request r.StatusCode: %v", r.StatusCode)
// For replaceBinary option response doesn't contain any result but just a message saying that product successfully replaced.
if replaceBinary && r.StatusCode == 201 {
result := new(ResultData)
result.Result.ProductID = productID
// log.Entry().Debugf("[DEBUG] ===> Return 'replaceBinary && r.StatusCode == 201' from 'UploadScanFile' : %v", result)
return result
} else {
result := new(ResultData)
pc.mapResponse(r.Body, result)
// log.Entry().Debugf("[DEBUG] ===> Return '!replaceBinary' from 'UploadScanFile' : %v", result)
return result
}
@@ -381,22 +377,15 @@ func (pc *Protecode) DeclareFetchURL(cleanupMode, group, fetchURL, version strin
var headers = make(map[string][]string)
if (replaceBinary) && (version != "") {
log.Entry().Debugf("[DEBUG][FETCH_URL] ===> replaceBinary && version != empty ")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Replace": {fmt.Sprintf("%v", productID)}, "Version": {version}, "Url": {fetchURL}, "Content-Type": {"application/json"}}
} else if replaceBinary {
log.Entry().Debugf("[DEBUG][FETCH_URL] ===> replaceBinary")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Replace": {fmt.Sprintf("%v", productID)}, "Url": {fetchURL}, "Content-Type": {"application/json"}}
} else if version != "" {
log.Entry().Debugf("[DEBUG][FETCH_URL] ===> version != empty ")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Version": {version}, "Url": {fetchURL}, "Content-Type": {"application/json"}}
} else {
log.Entry().Debugf("[DEBUG][FETCH_URL] ===> replaceBinary is false and version == empty")
headers = map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Url": {fetchURL}, "Content-Type": {"application/json"}}
}
// log.Entry().Debugf("[DEBUG] ===> Headers for fetch upload: %v", headers)
//headers := map[string][]string{"Group": {group}, "Delete-Binary": {fmt.Sprintf("%v", deleteBinary)}, "Url": {fetchURL}, "Content-Type": {"application/json"}}
protecodeURL := fmt.Sprintf("%v/api/fetch/", pc.serverURL)
r, statusCode, err := pc.sendAPIRequest(http.MethodPost, protecodeURL, headers)
if err != nil {
@@ -404,20 +393,15 @@ func (pc *Protecode) DeclareFetchURL(cleanupMode, group, fetchURL, version strin
pc.logger.WithError(err).Fatalf("Error during declare fetch url: %v", protecodeURL)
}
// log.Entry().Debugf("[DEBUG] ===> Fetch request r: %v", r)
// log.Entry().Debugf("[DEBUG] ===> Fetch request r.StatusCode: %v", statusCode)
// For replaceBinary option response doesn't contain any result but just a message saying that product successfully replaced.
if replaceBinary && statusCode == 201 {
result := new(ResultData)
result.Result.ProductID = productID
// log.Entry().Debugf("[DEBUG] ===> Fetch Return 'replaceBinary && statusCode == 201' from 'DeclareFetchURL' : %v", result)
return result
} else {
result := new(ResultData)
pc.mapResponse(*r, result)
// log.Entry().Debugf("[DEBUG] ===> Fetch Return '!replaceBinary' from 'DeclareFetchURL' : %v", result)
return result
}
@@ -511,8 +495,6 @@ func (pc *Protecode) pullResult(productID int) (ResultData, error) {
// verify provided product id
func (pc *Protecode) VerifyProductID(ProductID int) bool {
// pc.logger.Debugf("[DEBUG] ===> Verification of product id started ..... : %v", ProductID)
pc.logger.Infof("Verification of product id (%v) started ... ", ProductID)
// TODO: Optimise product id verification
@@ -537,17 +519,9 @@ func (pc *Protecode) LoadExistingProduct(group string, fileName string) int {
"acceptType": {"application/json"},
}
pc.logger.Debugf("[DEBUG] ===> LoadExistingProduct searching a product (%v) with URL: %v", fileName, protecodeURL)
// pc.logger.Infof("[DEBUG] ===> LoadExistingProduct searching a product (%v) with URL: %v", fileName, protecodeURL)
response := pc.loadExisting(protecodeURL, headers)
// pc.logger.Debugf("[DEBUG] ===> LoadExistingProduct response obj: %v", response)
if len(response.Products) > 0 {
// pc.logger.Debugf("[DEBUG] ===> LoadExistingProduct: response.Product obj: %v", response.Products)
// Highest product id means the latest scan for this particular product, therefore we take a product id with the highest number
for i := 0; i < len(response.Products); i++ {
// Check filename, it should be the same as we searched
@@ -559,11 +533,6 @@ func (pc *Protecode) LoadExistingProduct(group string, fileName string) int {
}
}
//productID = response.Products[0].ProductID
pc.logger.Debugf("[DEBUG] ===> Re-use existing Protecode scan - group: %v, productID: %v", group, productID)
// pc.logger.Infof("Automatic product id detection completed: %v", productID)
return productID
}

View File

@@ -13,6 +13,9 @@ spec:
- name: protecodeCredentialsId
description: Jenkins 'Username with password' credentials ID containing username and password to authenticate to the Protecode system.
type: jenkins
- name: protecodeApiKeyCredentialsId
description: Jenkins 'Secret text' credentials ID containing API Key/token to authenticate to BDBA server.
type: jenkins
- name: dockerConfigJsonCredentialsId
description: Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)). You can create it like explained in [Prerequisites](https://www.project-piper.io/steps/protecodeExecuteScan/#prerequisites).
type: jenkins
@@ -199,6 +202,21 @@ spec:
- type: vaultSecret
name: protecodeVaultSecretName
default: protecode
- name: userAPIKey
type: string
description: User API key which is used for API calls. Replacement for username and password / basic authentication.
scope:
- PARAMETERS
- STAGES
- STEPS
secret: true
resourceRef:
- name: protecodeApiKeyCredentialsId
type: secret
param: userAPIKey
- type: vaultSecret
name: protecodeApiKeyVaultSecretName
default: protecode
- name: version
aliases:
- name: artifactVersion

View File

@@ -13,6 +13,7 @@ void call(Map parameters = [:]) {
List credentials = [
[type: 'usernamePassword', id: 'protecodeCredentialsId', env: ['PIPER_username', 'PIPER_password']],
[type: 'file', id: 'dockerConfigJsonCredentialsId', env: ['PIPER_dockerConfigJSON']],
[type: 'token', id: 'protecodeApiKeyCredentialsId', env: ['PIPER_userAPIKey']],
]
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
}