mirror of
https://github.com/trailofbits/algo.git
synced 2025-07-13 17:22:56 +02:00
Added region-select and env secrets to lightsail
This commit is contained in:
parent
bfd0895159
commit
16b5e55c84
3 changed files with 128 additions and 72 deletions
|
@ -12,6 +12,7 @@ from playbook import PlaybookCLI
|
|||
|
||||
try:
|
||||
import boto3
|
||||
|
||||
HAS_BOTO3 = True
|
||||
except ImportError:
|
||||
HAS_BOTO3 = False
|
||||
|
@ -19,6 +20,7 @@ except ImportError:
|
|||
try:
|
||||
from google.auth.transport.requests import AuthorizedSession
|
||||
from google.oauth2 import service_account
|
||||
|
||||
HAS_GOOGLE_LIBRARIES = True
|
||||
except ImportError:
|
||||
HAS_GOOGLE_LIBRARIES = False
|
||||
|
@ -117,16 +119,14 @@ async def post_exit(_):
|
|||
|
||||
@routes.get('/do_config')
|
||||
async def check_do_config(_):
|
||||
return web.json_response({"ok": 'DO_API_TOKEN' in os.environ})
|
||||
return web.json_response({'has_secret': 'DO_API_TOKEN' in os.environ})
|
||||
|
||||
|
||||
@routes.get('/do_regions')
|
||||
@routes.post('/do_regions')
|
||||
async def do_regions(request):
|
||||
if 'token' in request.query:
|
||||
token = request.query['token']
|
||||
elif 'DO_API_TOKEN' in os.environ:
|
||||
token = os.environ['DO_API_TOKEN']
|
||||
else:
|
||||
data = await request.json()
|
||||
token = data.get('token', os.environ.get('DO_API_TOKEN'))
|
||||
if not token:
|
||||
return web.json_response({'error': 'no token provided'}, status=400)
|
||||
|
||||
headers = {
|
||||
|
@ -139,6 +139,13 @@ async def do_regions(request):
|
|||
return web.json_response(json_body, status=r.status)
|
||||
|
||||
|
||||
@routes.get('/aws_config')
|
||||
async def aws_config(_):
|
||||
if not HAS_BOTO3:
|
||||
return web.json_response({'error': 'missing_boto'}, status=400)
|
||||
return web.json_response({'has_secret': 'AWS_ACCESS_KEY_ID' in os.environ and 'AWS_SECRET_ACCESS_KEY' in os.environ})
|
||||
|
||||
|
||||
@routes.post('/lightsail_regions')
|
||||
async def lightsail_regions(request):
|
||||
data = await request.json()
|
||||
|
@ -195,9 +202,9 @@ async def gce_regions(request):
|
|||
response = AuthorizedSession(
|
||||
service_account.Credentials.from_service_account_info(
|
||||
data).with_scopes(
|
||||
['https://www.googleapis.com/auth/compute'])).get(
|
||||
'https://www.googleapis.com/compute/v1/projects/{project_id}/regions'.format(
|
||||
project_id=data['project_id'])
|
||||
['https://www.googleapis.com/auth/compute'])).get(
|
||||
'https://www.googleapis.com/compute/v1/projects/{project_id}/regions'.format(
|
||||
project_id=data['project_id'])
|
||||
)
|
||||
|
||||
return web.json_response(json.loads(response.content))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="form-group">
|
||||
<label for="id_do_token">
|
||||
Enter your API token. The token must have read and write permissions
|
||||
(<a href="https://cloud.digitalocean.com/settings/api/tokens" target="_blank" rel="noopener noreferrer">https://cloud.digitalocean.com/settings/api/tokens</a>):
|
||||
<a href="https://cloud.digitalocean.com/settings/api/tokens" title="https://cloud.digitalocean.com/settings/api/tokens" class="badge bagde-pill badge-primary" target="_blank" rel="noopener noreferrer">?</a>
|
||||
</label>
|
||||
<div v-if="ui_token_from_env">
|
||||
<input
|
||||
|
@ -67,7 +67,7 @@ module.exports = {
|
|||
return fetch("/do_config")
|
||||
.then(r => r.json())
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
if (response.has_secret) {
|
||||
this.ui_token_from_env = true;
|
||||
this.load_regions();
|
||||
}
|
||||
|
@ -80,8 +80,16 @@ module.exports = {
|
|||
if (this.ui_token_from_env || this.do_token) {
|
||||
this.ui_loading_regions = true;
|
||||
this.ui_region_error = null;
|
||||
const url = this.ui_token_from_env ? "/do_regions" : "/do_regions?token=" + this.do_token;
|
||||
fetch(url)
|
||||
const payload = this.ui_token_from_env ? {} : {
|
||||
token: this.do_token
|
||||
};
|
||||
fetch("/do_regions", {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then((r) => {
|
||||
if (r.status === 200) {
|
||||
return r.json();
|
||||
|
|
|
@ -1,47 +1,43 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
Enter your AWS Access Key <a href="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" title="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" target="_blank" rel="noreferrer noopener" class="badge bagde-pill badge-primary">?</a>
|
||||
<br>
|
||||
Note: Make sure to use an IAM user with an acceptable policy attached (see <a
|
||||
href="https://github.com/trailofbits/algo/blob/master/docs/deploy-from-ansible.md" target="_blank" rel="noreferrer noopener" >docs</a>)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="aws_access_key"
|
||||
v-on:blur="load_regions"
|
||||
v-model="aws_access_key"
|
||||
/>
|
||||
<div v-if="ui_config_error && ui_config_error === 'missing_boto'" class="form-text alert alert-danger" role="alert">
|
||||
Python module "boto3" is missing, please install it to proceed
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Enter your AWS Secret Key <a
|
||||
href="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" title="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" target="_blank" rel="noreferrer noopener" class="badge bagde-pill badge-primary">?</a></label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="aws_secret_key"
|
||||
v-on:blur="load_regions"
|
||||
v-model="aws_secret_key">
|
||||
<div v-if="ui_env_secrets" class="form-text alert alert-success" role="alert">
|
||||
AWS credentials were read from the environment variables
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label v-if="lightsail_regions.length === 0">Please enter Access key and Secret key to select region</label>
|
||||
<label v-if="is_loading">Loading regions...</label>
|
||||
<label v-if="lightsail_regions.length > 0">What region should the server be located in?</label>
|
||||
<select name="region"
|
||||
class="form-control"
|
||||
v-model="region"
|
||||
v-bind:disabled="is_region_disabled">
|
||||
<option value disabled>Select region</option>
|
||||
<option
|
||||
v-for="(region, i) in lightsail_regions"
|
||||
v-bind:key="region.displayName"
|
||||
v-bind:value="region.name"
|
||||
>{{region.displayName}}</option>
|
||||
</select>
|
||||
|
||||
<div v-else>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
Enter your AWS Access Key <a href="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" title="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" target="_blank" rel="noreferrer noopener" class="badge bagde-pill badge-primary">?</a>
|
||||
<br>
|
||||
Note: Make sure to use an IAM user with an acceptable policy attached (see <a
|
||||
href="https://github.com/trailofbits/algo/blob/master/docs/deploy-from-ansible.md" target="_blank" rel="noreferrer noopener" >docs</a>)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="aws_access_key"
|
||||
v-on:blur="load_regions"
|
||||
v-model="aws_access_key"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Enter your AWS Secret Key <a
|
||||
href="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" title="http://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html" target="_blank" rel="noreferrer noopener" class="badge bagde-pill badge-primary">?</a></label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="aws_secret_key"
|
||||
v-on:blur="load_regions"
|
||||
v-model="aws_secret_key">
|
||||
</div>
|
||||
</div>
|
||||
<region-select v-model="region"
|
||||
v-bind:options="ui_region_options"
|
||||
v-bind:loading="ui_loading_check || ui_loading_regions"
|
||||
v-bind:error="ui_region_error">
|
||||
</region-select>
|
||||
<button class="btn btn-primary"
|
||||
type="button"
|
||||
v-on:click="submit"
|
||||
|
@ -58,48 +54,93 @@ module.exports = {
|
|||
aws_access_key: null,
|
||||
aws_secret_key: null,
|
||||
region: null,
|
||||
lightsail_regions: [],
|
||||
is_loading: false
|
||||
// ui helpoer variables
|
||||
ui_region_options: [],
|
||||
ui_env_secrets: null,
|
||||
ui_loading_check: false,
|
||||
ui_loading_regions: false,
|
||||
ui_config_error: null,
|
||||
ui_region_error: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
is_valid() {
|
||||
return this.aws_access_key && this.aws_secret_key && this.region;
|
||||
has_secrets() {
|
||||
return this.ui_env_secrets || (this.aws_access_key && this.aws_secret_key);
|
||||
},
|
||||
is_region_disabled() {
|
||||
return !(this.aws_access_key && this.aws_secret_key) || this.is_loading;
|
||||
is_valid() {
|
||||
return this.has_secrets && this.region;
|
||||
}
|
||||
},
|
||||
created: function() {
|
||||
this.check_config();
|
||||
},
|
||||
methods: {
|
||||
check_config() {
|
||||
this.ui_loading_check = true;
|
||||
fetch("/aws_config")
|
||||
.then(r => {
|
||||
if (r.status === 200 || r.status === 400) {
|
||||
return r.json();
|
||||
}
|
||||
throw new Error(r.status);
|
||||
})
|
||||
.then(response => {
|
||||
if (response.has_secret) {
|
||||
this.ui_env_secrets = true;
|
||||
this.load_regions();
|
||||
} else if (response.error) {
|
||||
this.ui_config_error = response.error;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.ui_loading_check = false;
|
||||
});
|
||||
},
|
||||
load_regions() {
|
||||
if (this.aws_access_key && this.aws_secret_key && this.lightsail_regions.length === 0) {
|
||||
this.is_loading = true;
|
||||
if (this.has_secrets && this.ui_region_options.length === 0) {
|
||||
this.ui_loading_regions = true;
|
||||
this.ui_region_error = false;
|
||||
const payload = this.ui_env_secrets ? {} : {
|
||||
aws_access_key: this.aws_access_key,
|
||||
aws_secret_key: this.aws_secret_key
|
||||
}
|
||||
fetch('/lightsail_regions', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
aws_access_key: this.aws_access_key,
|
||||
aws_secret_key: this.aws_secret_key
|
||||
})
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then((r) => {
|
||||
if (r.status === 200) {
|
||||
return r.json();
|
||||
}
|
||||
throw new Error(r.status);
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
this.lightsail_regions = data.regions;
|
||||
this.ui_region_options = data.regions.map(i => ({key: i.name, value: i.displayName}));
|
||||
})
|
||||
.catch((err) => {
|
||||
this.ui_region_error = err;
|
||||
})
|
||||
.finally(() => {
|
||||
this.is_loading = false;
|
||||
this.ui_loading_regions = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
submit() {
|
||||
this.$emit('submit', {
|
||||
aws_access_key: this.aws_access_key,
|
||||
aws_secret_key: this.aws_secret_key,
|
||||
let submit_value = {
|
||||
region: this.region
|
||||
});
|
||||
}
|
||||
if (!this.ui_env_secrets) {
|
||||
submit_value['aws_access_key'] = this.aws_access_key;
|
||||
submit_value['aws_secret_key'] = this.aws_secret_key;
|
||||
}
|
||||
this.$emit('submit', submit_value);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"region-select": window.httpVueLoader("/static/region-select.vue"),
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
Loading…
Add table
Reference in a new issue