Skip to content
Snippets Groups Projects
Commit d86a4bf7 authored by hahn's avatar hahn
Browse files

task#3869 - initial stuff for API

parent 55e46a4f
Branches
No related tags found
No related merge requests found
......@@ -214,6 +214,9 @@
"accept": "Accept",
"accept-hint": "Accept Phase [%s] und in die Queue von Phase [%s] stellen.",
"all": "alle",
"api-secret": "Secret für API Zugriff",
"api-secret-hint": "Hinweise: Bei leeren Secret ist der Zugriff via API deaktiviert. Um den API Zugriff zu aktivieren, ist ein geshartes Secret zu setzen. Ein Neusetzen eines Secrets macht den bisherigen Key ungültig.",
"api-secret-generate": "Neues Secret erzeugen",
"archive": "Archiv",
"back": "zurück",
"branch": "Branch/ Tag",
......@@ -238,7 +241,7 @@
"delete": "Löschen",
"deploy": "Deploy",
"deploy-configfile": "Konfiguration",
"deploy-configfile-hint": "Hier können Variablen in Bash-Syntax hinterlegt werden, die sich vom onbuild oder ondeploy Hook lesen lassen.",
"deploy-configfile-hint": "Hier können Variablen in Bash-Syntax hinterlegt werden. Bei einem Build werden diese in [root]/ci-custom-vars geschrieben und lassen sich vom onbuild oder ondeploy Hook lesen.",
"deploy-hint": "Deploy der Queue von Phase [%s]",
"deploy-impossible": "Deploy der Queue von Phase [%s] ist nicht möglich.",
"deploy-settings": "Deployment-Einstellungen",
......
......@@ -216,6 +216,9 @@
"accept": "Accept",
"accept-hint": "Accept phase [%s] and put package to the queue of phase [%s].",
"all": "all",
"api-secret": "Secret for API access",
"api-secret-hint": "To enable access via API it is required to set a shared secret. If you set a new key then the former key is invalid.",
"api-secret-generate": "Generate new secret",
"archive": "Archive",
"back": "back",
"branch": "Branch/ tag",
......@@ -240,7 +243,7 @@
"delete": "Delete",
"deploy": "Deploy",
"deploy-configfile": "Configuration",
"deploy-configfile-hint": "Here you can place variables in Bash syntax that onbuild oder ondeploy hook can read.",
"deploy-configfile-hint": "Here you can place variables in Bash syntax. During the build it will be writen as [root]/ci-custom-vars and is readable in the onbuild oder ondeploy hook.",
"deploy-hint": "Deploy queue of phase [%s]",
"deploy-impossible": "Deploy queue of phase [%s] is not possible.",
"deploy-settings": "Deployment settings",
......
......@@ -3,12 +3,12 @@
* IDEA TO REALIZE:
*
* /api/v1/projects/
* /api/v1/project/[Name]/[token]/build[/[name-of-branch]]
* /api/v1/project/[Name]/[token]/accept/[phase]
* /api/v1/project/[Name]/build/[name-of-branch]]
* /api/v1/project/[Name]/accept/[phase]
*
*/
$bDebug=true;
$bDebug=false;
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
......@@ -25,23 +25,39 @@
// ----------------------------------------------------------------------
// FUNCTIONS
// ----------------------------------------------------------------------
/**
* write debug text (if enabled)
* @global boolean $bDebug
* @param string $s message
* @param string $sLevel level; one of info|
* @return boolean
*/
function _wd($s, $sLevel='info'){
global $bDebug;
if ($bDebug){
echo '<div class="debug ">DEBUG: '.$s.'</div>';
echo '<div class="debug debug-'.$sLevel.'">DEBUG: '.$s.'</div>';
}
return true;
}
/**
* abort execution with error
* @param string $s message
* @param integer $iStatus http status code to send
*/
function _quit($s, $iStatus=400){
$aStatus=array(
400=>'HTTP/1.0 400 Bad Request',
404=>'HTTP/1.0 403 Access denied',
403=>'HTTP/1.0 403 Access denied',
404=>'HTTP/1.0 404 Not found',
);
header($aStatus[$iStatus]);
_done(array('status'=>$iStatus, 'info'=>$aStatus[$iStatus], 'message'=>$s));
}
/**
* end with OK output
* @param type $Data
*/
function _done($Data){
echo is_array($Data)
? json_encode($Data, 1, JSON_PRETTY_PRINT)
......@@ -71,14 +87,13 @@
_wd('<pre>$aUriSplit: '.print_r($aUriSplit, 1).'</pre>');
/*
/api/v1/projects/ci/my-token/build?auth=123
/api/v1/projects/ci/build?auth=123
$aUriSplit: Array
(
[0] => v1
[1] => projects
[2] => ci
[3] => my-token
[4] => build
[3] => build
)
*/
$sApiVersion = isset($aUriSplit[0]) ? $aUriSplit[0] : false;
......@@ -107,26 +122,35 @@
_wd('<pre>'.print_r($aList,1).'</pre>');
_done($aList);
break;;
case 'project':
// path /api/v1/project
$sPrjId = isset($aUriSplit[2]) ? $aUriSplit[2] : false;
$sPrjToken = isset($aUriSplit[3]) ? $aUriSplit[3] : false;
$sPrjAction = isset($aUriSplit[4]) ? $aUriSplit[4] : false;
$sPrjAction = isset($aUriSplit[3]) ? $aUriSplit[3] : false;
_wd('$sPrjId = '.$sPrjId);
_wd('$sPrjToken = '.$sPrjToken);
_wd('$sPrjAction = '.$sPrjAction);
$oProject=new project();
if(!in_array($sPrjId, $oProject->getProjects())){
_quit('ERROR: project with id ['.$sPrjId.'] does not exist.');
// try to init the given project
try{
ob_start();
$oProject=new project($sPrjId);
$oProject->setProjectById($sPrjId);
ob_end_clean();
} catch (Exception $exc) {
_quit('ERROR: project with id ['.$sPrjId.'] does not exist.', 404);
}
$oProject->setProjectById($sPrjId);
_wd('TODO: verify given token with that in the config.');
// get secret
$aPrjCfg=$oProject->getConfig();
_wd('<pre>'.print_r($aPrjCfg, 1).'</pre>');
$sProjectSecret=isset($aPrjCfg['api']['secret']) ? $aPrjCfg['api']['secret'] : false;
if(!$sProjectSecret){
_quit('Access denied. API access is disabled.');
}
$aReqHeaders=apache_request_headers();
_wd('<pre>'.print_r($aReqHeaders, 1).'</pre>');
break;;
default:
......
......@@ -195,8 +195,10 @@ class project extends base {
* @return boolean
*/
private function _verifyConfig() {
if (!count($this->_aPrjConfig))
die(t("class-project-error-no-config"));
if (!count($this->_aPrjConfig)){
// die(t("class-project-error-no-config"));
throw new Exception(t("class-project-error-no-config"));
}
if (!array_key_exists("packageDir", $this->_aConfig)) {
die(t("class-project-error-no-packagedir"));
......@@ -3508,7 +3510,25 @@ class project extends base {
'cols' => 100,
'rows' => 10,
'placeholder' => 'export myvariable=&quot;hello world&quot;',
),
'input' . $i++ => array(
'type' => 'text',
'name' => 'api[secret]',
'label' => t("api-secret"),
'value' => $this->_aPrjConfig["api"]["secret"],
'validate' => 'isastring',
'size' => 100,
'placeholder' => '',
),
'input' . $i++ => array(
'type' => 'markup',
'value' => '<div class="col-sm-12">'
. '<p>' . t('api-secret-hint') . '<br>'
. '<a href="#" class="btn btn-default" onclick="$(\'#input'.($i-2).'\').val(generateSecret(64)); return false">'.t("api-secret-generate").'</a>'
. '</p></div>',
),
// --------------------------------------------------
'input' . $i++ => array(
'type' => 'markup',
......
This diff is collapsed.
#!/bin/bash
# ======================================================================
#
# API CLIENT :: proof of concept
#
# This is a demo api client
#
# ----------------------------------------------------------------------
# 2020-06-12 first lines <axel.hahn@iml.unibe.ch>
# ======================================================================
# ----------------------------------------------------------------------
# CONFIG
# ----------------------------------------------------------------------
myProject=ci-webgui
secret="cOiScVAElvcJKmJ1eGrKXZvv6ZROlSgZ9VpSVFK1uxZI8J5ITXuZZb8jIYobuoAB"
myAction=build
apiHost="http://dev.ci.iml.unibe.ch:8002"
apiBaseUrl="/api/v1"
apiMethod=GET
# ----------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------
# --- build url
apiRequest="${apiBaseUrl}/project/${myProject}/${myAction}"
# --- generate auth
data="`date`\n${apiMethod}\n${apiRequest}"
myHash=`echo -n "$data" | openssl sha1 -hmac "${secret}" | cut -f 2 -d" "`
# https://stackoverflow.com/questions/356705/how-to-send-a-header-using-a-http-request-through-a-curl-call
echo HASH: $myHash ... made from [$data]
echo REQEST: $apiRequest - $myHash
curl -i \
-H "Accept: application/json" -H "Content-Type: application/json" \
-H "Authorization: demo-bash-client:${myHash}" \
-X $apiMethod \
${apiHost}${apiRequest}
rc=$?
echo rc = $rc
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment