forked from SAP/InfraBox
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
716d983
commit 10e48a1
Showing
10 changed files
with
324 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import re | ||
|
||
from flask import request, g, abort | ||
from flask_restplus import Resource, fields | ||
|
||
from pyinfrabox.utils import validate_uuid | ||
from pyinfraboxutils.ibflask import OK | ||
from pyinfraboxutils.ibrestplus import api, response_model | ||
|
||
from croniter import croniter | ||
|
||
ns = api.namespace('SSHKeys', | ||
path='/api/v1/projects/<project_id>/sshkeys', | ||
description='SSH Key related operations') | ||
|
||
sshkey_model = api.model('CronJob', { | ||
'name': fields.String(required=True), | ||
'id': fields.String(required=True), | ||
'secret': fields.String(required=True), | ||
}) | ||
|
||
add_sshkey_model = api.model('AddCronJob', { | ||
'name': fields.String(required=True, max_length=255), | ||
'secret': fields.String(required=True, max_length=255), | ||
}) | ||
|
||
@ns.route('/') | ||
@api.doc(responses={403: 'Not Authorized'}) | ||
class SSHKeys(Resource): | ||
|
||
name_pattern = re.compile('^[a-zA-Z0-9_]+$') | ||
|
||
@api.marshal_list_with(sshkey_model) | ||
def get(self, project_id): | ||
''' | ||
Returns project's sshkeys | ||
''' | ||
p = g.db.execute_many_dict(''' | ||
SELECT k.id, k.name, s.name as secret | ||
FROM sshkey k | ||
JOIN secret s | ||
ON s.id = k.secret_id | ||
WHERE s.project_id = %s | ||
AND k.project_id = %s | ||
''', [project_id, project_id]) | ||
return p | ||
|
||
@api.expect(add_sshkey_model) | ||
@api.response(200, 'Success', response_model) | ||
def post(self, project_id): | ||
''' | ||
Add new sshkey | ||
''' | ||
b = request.get_json() | ||
|
||
if not CronJobs.name_pattern.match(b['name']): | ||
abort(400, 'CronJob name must be not empty alphanumeric string.') | ||
|
||
result = g.db.execute_one_dict(""" | ||
SELECT id | ||
FROM secret | ||
WHERE project_id = %s | ||
AND name = %s | ||
""", [project_id, b['secret']]) | ||
|
||
if not result: | ||
abort(400, 'Secret does not exist') | ||
|
||
secret_id = result['id'] | ||
|
||
result = g.db.execute_one_dict(""" | ||
SELECT COUNT(*) as cnt | ||
FROM sshkey | ||
WHERE project_id = %s | ||
""", [project_id]) | ||
|
||
if result['cnt'] > 50: | ||
abort(400, 'Too many sshkeys.') | ||
|
||
r = g.db.execute_one(""" | ||
SELECT count(*) | ||
FROM sshkey | ||
WHERE project_id = %s | ||
AND name = %s | ||
""", [project_id, b['name']]) | ||
|
||
if r[0] > 0: | ||
abort(400, 'SSH Key with this name already exist') | ||
|
||
g.db.execute(''' | ||
INSERT INTO sshkey (project_id, name, secret_id) VALUES(%s, %s, %s) | ||
''', [project_id, b['name'], secret_id]) | ||
|
||
g.db.commit() | ||
|
||
return OK('Successfully added SSH Key') | ||
|
||
@ns.route('/<sshkey_id>') | ||
@api.doc(responses={403: 'Not Authorized'}) | ||
class CronJob(Resource): | ||
@api.response(200, 'Success', response_model) | ||
def delete(self, project_id, sshkey_id): | ||
''' | ||
Delete a sshkey | ||
''' | ||
if not validate_uuid(sshkey_id): | ||
abort(400, "Invalid sshkey uuid.") | ||
|
||
num_sshkeys = g.db.execute_one(""" | ||
SELECT COUNT(*) FROM sshkey | ||
WHERE project_id = %s and id = %s | ||
""", [project_id, sshkey_id])[0] | ||
|
||
if num_sshkeys == 0: | ||
return abort(400, 'SSH Key does not exist.') | ||
|
||
g.db.execute(""" | ||
DELETE FROM sshkey WHERE project_id = %s and id = %s | ||
""", [project_id, sshkey_id]) | ||
g.db.commit() | ||
|
||
return OK('Successfully deleted SSH Key.') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<template> | ||
<div class="m-sm full-height"> | ||
<md-card md-theme="white" class="full-height clean-card"> | ||
<md-card-header> | ||
<md-card-header-text class="setting-list"> | ||
<md-icon>security</md-icon> | ||
<span>SSHKeys</span> | ||
</md-card-header-text> | ||
</md-card-header> | ||
<md-card-area> | ||
<md-list class="m-t-md m-b-md md-double-line"> | ||
<md-list-item> | ||
<div class="md-list-text-container"> | ||
<span> | ||
<md-input-container> | ||
<label>Name</label> | ||
<md-input @keyup.enter.native="addSSHKey" required v-model="name"></md-input> | ||
</md-input-container> | ||
</span> | ||
</div> | ||
|
||
<div class="md-list-text-container"> | ||
<span> | ||
<md-input-container> | ||
<label for="secret_select">Secret</label> | ||
<md-select name="secret_select" id="secret_select" v-model="secret"> | ||
<md-option v-for="s in project.secrets" :value=r :key="s.name" class="bg-white">{{s.name}}</md-option> | ||
</md-select> | ||
</md-input-container> | ||
</span> | ||
</div> | ||
|
||
<md-button class="md-icon-button md-list-action" @click="addSSHKey()"> | ||
<md-icon md-theme="running" class="md-primary">add_circle</md-icon> | ||
<md-tooltip>Add SSH Key</md-tooltip> | ||
</md-button> | ||
</md-list-item> | ||
<md-list-item v-for="k in project.sshkeys" :key="k.id"> | ||
<md-input-container class="m-l-sm"> | ||
{{ k.name }} | ||
</md-input-container> | ||
<md-input-container class="m-l-sm"> | ||
{{ k.secret }} | ||
</md-input-container> | ||
<md-button class="md-icon-button md-list-action" @click="project.removeSSHKey(co)"> | ||
<md-icon class="md-primary">delete</md-icon> | ||
<md-tooltip>Remove sshkey</md-tooltip> | ||
</md-button> | ||
</md-list-item> | ||
</md-list> | ||
</md-card-area> | ||
</md-card> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
export default { | ||
props: ['project'], | ||
data: () => { | ||
return { | ||
'name': '', | ||
'secret': '' | ||
} | ||
}, | ||
created () { | ||
this.project._loadSSHKeys() | ||
}, | ||
methods: { | ||
deleteSSHKEY (id) { | ||
NewAPIService.delete(`projects/${this.project.id}/sshkeys/${id}`) | ||
.then((response) => { | ||
NotificationService.$emit('NOTIFICATION', new Notification(response)) | ||
this.project._reloadSSHKeys() | ||
}) | ||
.catch((err) => { | ||
NotificationService.$emit('NOTIFICATION', new Notification(err)) | ||
}) | ||
}, | ||
addCronJob () { | ||
const d = { | ||
name: this.name, | ||
secret: this.secret | ||
} | ||
NewAPIService.post(`projects/${this.project.id}/sshkeys`, d) | ||
.then((response) => { | ||
NotificationService.$emit('NOTIFICATION', new Notification(response)) | ||
this.name = '' | ||
this.minute = '' | ||
this.project._reloadSSHKeys() | ||
}) | ||
.catch((err) => { | ||
NotificationService.$emit('NOTIFICATION', new Notification(err)) | ||
}) | ||
} | ||
} | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
ALTER TABLE "commit" ADD COLUMN gerrit_change_id varchar; | ||
ALTER TABLE "commit" ADD COLUMN gerrit_change_id varchar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CREATE TABLE sshkey ( | ||
project_id uuid NOT NULL, | ||
id uuid DEFAULT gen_random_uuid() NOT NULL, | ||
name character varying(255) NOT NULL, | ||
secret_id uuid NOT NULL | ||
); | ||
|
||
ALTER TABLE ONLY sshkey | ||
ADD CONSTRAINT sshkey_pkey PRIMARY KEY (id); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package infrabox | ||
|
||
import input as api | ||
|
||
import data.infrabox.collaborators.collaborators | ||
import data.infrabox.projects.projects | ||
import data.infrabox.roles | ||
|
||
projects_sshkeys_administrator([user, project]){ | ||
collaborators[i].project_id = project | ||
collaborators[i].user_id = user | ||
roles[collaborators[i].role] >= 20 | ||
} | ||
|
||
# Allow GET access to /api/v1/projects/<project_id>/sshkeys for project administrators | ||
allow { | ||
api.method = "GET" | ||
api.path = ["api", "v1", "projects", project_id, "sshkeys"] | ||
api.token.type = "user" | ||
projects_sshkeys_administrator([api.token.user.id, project_id]) | ||
} | ||
|
||
# Allow POST access to /api/v1/projects/<project_id>/sshkeys for project administrators | ||
allow { | ||
api.method = "POST" | ||
api.path = ["api", "v1", "projects", project_id, "sshkeys"] | ||
api.token.type = "user" | ||
projects_sshkeys_administrator([api.token.user.id, project_id]) | ||
} | ||
|
||
# Allow DELETE access to /api/v1/projects/<project_id>/sshkeys/<cronjob_id> for project administrators | ||
allow { | ||
api.method = "DELETE" | ||
api.path = ["api", "v1", "projects", project_id, "sshkeys", cronjob_id] | ||
api.token.type = "user" | ||
projects_sshkeys_administrator([api.token.user.id, project_id]) | ||
} |
Oops, something went wrong.