From 6b595fa4a3b0d9d9b6434fa255f615b6585305f7 Mon Sep 17 00:00:00 2001
From: "Hahn Axel (hahn)" <axel.hahn@unibe.ch>
Date: Wed, 19 Feb 2025 13:26:22 +0100
Subject: [PATCH 1/2] more clear HTTP responses on error

---
 public_html/api/index.php | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/public_html/api/index.php b/public_html/api/index.php
index 15c0b25a..7b197c9c 100644
--- a/public_html/api/index.php
+++ b/public_html/api/index.php
@@ -59,7 +59,7 @@ function _wd(string $s, string $sLevel = 'info'): bool
 }
 
 /**
- * Abort execution of API requestwith error
+ * Abort execution of API request with error
  * 
  * @param string   $s        message
  * @param integer  $iStatus  http status code to send
@@ -68,6 +68,7 @@ function _quit(string $s, int $iStatus = 400): void
 {
     $aStatus = [
         400 => 'HTTP/1.0 400 Bad Request',
+        401 => 'HTTP/1.0 401 Unauthorized',
         403 => 'HTTP/1.0 403 Access denied',
         404 => 'HTTP/1.0 404 Not found',
     ];
@@ -105,7 +106,7 @@ function _checkAuth(string $sProjectSecret): bool
     $aReqHeaders = apache_request_headers();
     _wd('<pre>' . print_r($aReqHeaders, 1) . '</pre>');
     if (!isset($aReqHeaders['Authorization'])) {
-        _quit('Access denied. Missing authorization.', 403);
+        _quit('Access denied. Missing authorization.', 401);
     }
     if (!isset($aReqHeaders['Date'])) {
         _quit('Access denied. Missing field "Date:" in the request header.', 403);
@@ -123,7 +124,7 @@ function _checkAuth(string $sProjectSecret): bool
     _wd('Hash: ' . $sGotHash . ' -- from header');
     _wd('Hash: ' . $sMyHash . ' -- rebuilt');
     if ($sGotHash !== $sMyHash) {
-        _quit('Access denied. Invalid hash.', 403);
+        _quit('Access denied. Invalid hash.', 401);
     }
 
     $iAge = date('U') - date('U', strtotime($sGotDate));
@@ -216,14 +217,18 @@ switch ($sApiVersion) {
                     ob_end_clean();
 
                 } catch (Exception $exc) {
-                    _quit('ERROR: project with id [' . $sPrjId . '] does not exist.', 404);
+                    _quit('ERROR: project with id [' . $sPrjId . '] cannot be initialized.', 400); // never reached
                 }
 
                 // get secret
                 $aPrjCfg = $oProject->getConfig();
-                $sProjectSecret = isset($aPrjCfg['api']['secret']) ? $aPrjCfg['api']['secret'] : false;
+                if(!count($aPrjCfg)){
+                    _quit('ERROR: project with id [' . $sPrjId . '] does not exist.', 404);
+                }
+
+                $sProjectSecret = $aPrjCfg['api']['secret'] ?? false;
                 if (!$sProjectSecret) {
-                    _quit('Access denied. API access is disabled.');
+                    _quit('Access denied. API access is disabled.', 403);
                 }
 
                 // check authorization 
-- 
GitLab


From b635762161a52e0d4380717fa59e2f683291448b Mon Sep 17 00:00:00 2001
From: "Hahn Axel (hahn)" <axel.hahn@unibe.ch>
Date: Wed, 19 Feb 2025 15:18:52 +0100
Subject: [PATCH 2/2] api shel script: shell fixes; long cli parameters

---
 shellscripts/api-imlciserver.sh | 124 ++++++++++++++++----------------
 1 file changed, 64 insertions(+), 60 deletions(-)

diff --git a/shellscripts/api-imlciserver.sh b/shellscripts/api-imlciserver.sh
index 099e7ff3..7b1932e5 100755
--- a/shellscripts/api-imlciserver.sh
+++ b/shellscripts/api-imlciserver.sh
@@ -7,6 +7,7 @@
 # 2020-07-23  v1.0  <axel.hahn@iml.unibe.ch>  first lines
 # 2020-07-29  v1.1  <axel.hahn@iml.unibe.ch>  check "/" in branch; check http status 200 
 # 2021-03-29  v1.2  <axel.hahn@iml.unibe.ch>  support slashes in branch names
+# 2025-02-19  v1.3  <axel.hahn@iml.unibe.ch>  shell fixes; long cli parameters
 # ======================================================================
 
 # ----------------------------------------------------------------------
@@ -22,30 +23,35 @@ line="----------------------------------------------------------------------"
 # FUNCTIONS
 # ----------------------------------------------------------------------
 
+# Show help with parameters
 function showhelp(){
+  local _self; _self="$( basename "$0" )"
 echo "
 SYNTAX:
-  -a ACTION     set name of an action
-  -b BRANCH     set custom branch to access, i.e. origin/feature-123
-  -p PROJECT    project name in the ci server; overrides env variable IMLCI_PROJECT
-  -s SECRET     API secret for the given project; overrides env variable IMLCI_API_SECRET
-  -u URL        URL of iml ci server without trailing /; overrides env variable IMLCI_URL
-
-ACTION:
-   ... without given project and secret
-     projects   show projects
-
-   ... with project and secret
-     buildinfo [branch]
-                show infos about what happens on build
-     build [branch]
-                execute build
-     phases     show status of phases
+  -a, --action ACTION     
+          set name of an action
+          ... without given project and secret
+              projects    show projects
+
+          ... with project and secret
+              buildinfo BRANCH
+                          show infos about what happens on build
+              build BRANCH
+                          execute build
+              phases      show status of phases
+  -b, --branch BRANCH
+          set custom branch to access, i.e. origin/feature-123
+  -p, --project PROJECT
+          project name in the ci server; overrides env variable IMLCI_PROJECT
+  -s, --secret SECRET
+          API secret for the given project; overrides env variable IMLCI_API_SECRET
+  -u. --url URL
+          URL of iml ci server without trailing /; overrides env variable IMLCI_URL
 
 EXAMPLES:
-  `basename $0` -u https://ci.example.com -a projects
-  `basename $0` -u https://ci.example.com -p myproject -s 12345678 -a buildinfo
-  `basename $0` -u https://ci.example.com -p myproject -s 12345678 -a build
+  $_self -u https://ci.example.com -a projects
+  $_self -u https://ci.example.com -p myproject -s 12345678 -a buildinfo
+  $_self -u https://ci.example.com -p myproject -s 12345678 -a build
 "
 }
 
@@ -59,7 +65,7 @@ function makeRequest(){
   local outfile=$( mktemp )
 
   echo $line
-  echo $apiMethod ${apiHost}${apiRequest}
+  echo "$apiMethod ${IMLCI_URL}${apiRequest}"
   echo $line
 
   if [ ! -z "$secret" ]; then
@@ -67,7 +73,7 @@ function makeRequest(){
     # --- date in http format
     LANG=en_EN
     # export TZ=GMT
-    apiTS=`date "+%a, %d %b %Y %H:%M:%S %Z"`
+    apiTS=$( date "+%a, %d %b %Y %H:%M:%S %Z" )
 
 
 # --- generate data to hash: method + uri + timestamp; delimited with line break
@@ -77,30 +83,32 @@ ${apiTS}
 "
 
     # generate hash - split in 2 commands (piping "cut" sends additional line break)
-    myHash=`echo -n "$data" | openssl sha1 -hmac "${secret}" | cut -f 2 -d" "`
-    myHash=`echo -n "$myHash" | base64`
+    myHash=$( echo -n "$data" | openssl sha1 -hmac "${secret}" | cut -f 2 -d" ")
+    myHash=$( echo -n "$myHash" | base64 )
 
     curl -i \
       -H "Accept: application/json" -H "Content-Type: application/json" \
       -H "Date: ${apiTS}" \
       -H "Authorization: demo-bash-client:${myHash}" \
-      -X $apiMethod \
-      ${IMLCI_URL}${apiRequest} | tee -a $outfile
+      -X "$apiMethod" \
+      -s \
+      "${IMLCI_URL}${apiRequest}" | tee -a "$outfile"
   else
     curl -i \
       -H "Accept: application/json" -H "Content-Type: application/json" \
-      -X $apiMethod \
-      ${IMLCI_URL}${apiRequest} | tee -a $outfile
+      -X "$apiMethod" \
+      -s \
+      "${IMLCI_URL}${apiRequest}" | tee -a "$outfile"
   fi
 
-  grep "^HTTP/" $outfile | head -1 | grep " 200 " >/dev/null
+  grep "^HTTP/" "$outfile" | head -1 | grep " 200 " >/dev/null
   local rccurl=$?
 
-  rm -f $outfile
+  rm -f "$outfile"
   if [ $rccurl -ne 0 ]; then
     echo
     echo "ERROR: API request failed. CURL request did not get respond status code 200."
-    exit 4
+    exit 5
   fi
 }
 
@@ -110,38 +118,34 @@ ${apiTS}
 # ----------------------------------------------------------------------
 
 echo
-echo ===== API CALL TO IML CI SERVER :: `date` =====
+echo "===== API CALL TO IML CI SERVER :: $( date ) ====="
 echo
 
-if  [ $# -lt 1 ]; then
+if  [ $# -eq 0 ]; then
   showhelp
   exit 1
 fi
 
-while getopts "a:b:u:p:s:" option; do 
-case ${option} in
-  a)
-    apiAction=$OPTARG
-    ;;
-  b)
-    branch=$OPTARG
-    ;;
-  u)
-    export IMLCI_URL=$OPTARG
-    ;;
-  p)
-    export IMLCI_PROJECT=$OPTARG
-    ;;
-  s)
-    export IMLCI_API_SECRET=$OPTARG
-    ;;
-  *)
-    echo ERROR: invalid option [${option}]
-    exit 2
-esac
-done
+while [[ "$#" -gt 0 ]]; do case $1 in
+    -a|--action)    apiAction="$2";shift; shift;;
+    -b|--branch)    branch="$2";shift; shift;;
+    -h|--help)      showhelp; exit 0;;
+    -u|--url)       IMLCI_URL="$2";shift; shift;;
+    -p|--project)   IMLCI_PROJECT="$2";shift; shift;;
+    -s|--secret)    IMLCI_API_SECRET="$2";shift; shift;;
+    *) if grep "^-" <<< "$1" >/dev/null ; then
+        echo; echo "ERROR: Unknown parameter: $1"; echo; showhelp; exit 2
+       fi
+       break;
+       ;;
+esac; done
+if  [ $# -gt 0 ]; then
+  showhelp
+  exit 3
+fi
+
 
-echo Params: $*
+echo "Params: $*"
 echo "IMLCI_URL = $IMLCI_URL"
 echo "IMLCI_PROJECT = $IMLCI_PROJECT"
 echo "IMLCI_API_SECRET = $IMLCI_API_SECRET"
@@ -151,7 +155,7 @@ echo
 # echo $branch | grep '/.*/.*' >/dev/null && ( echo "WARNING: Do NOT use a branch containing a slash [/] in the name"; echo )
 
 
-echo ACTION: $apiAction
+echo "ACTION: $apiAction"
 case $apiAction in
 
   # --- projects is an access without autorization
@@ -161,17 +165,17 @@ case $apiAction in
 
   # --- access WITH autorization only
   "build")
-    makeRequest POST /api/v1/project/$IMLCI_PROJECT/build/$branch "$IMLCI_API_SECRET"
+    makeRequest POST "/api/v1/project/$IMLCI_PROJECT/build/$branch" "$IMLCI_API_SECRET"
     ;;
   "buildinfo")
-    makeRequest GET  /api/v1/project/$IMLCI_PROJECT/build/$branch "$IMLCI_API_SECRET"
+    makeRequest GET  "/api/v1/project/$IMLCI_PROJECT/build/$branch" "$IMLCI_API_SECRET"
     ;;
   "phases")
-    makeRequest GET  /api/v1/project/$IMLCI_PROJECT/phases   "$IMLCI_API_SECRET"
+    makeRequest GET  "/api/v1/project/$IMLCI_PROJECT/phases"   "$IMLCI_API_SECRET"
     ;;
   *)
     echo "ERROR: unknown action [$apiAction]"
-    exit 3
+    exit 4
 esac
 
 rc=$?
-- 
GitLab