mirror of
https://github.com/trailofbits/algo.git
synced 2025-09-10 14:03:02 +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:
|
try:
|
||||||
import boto3
|
import boto3
|
||||||
|
|
||||||
HAS_BOTO3 = True
|
HAS_BOTO3 = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_BOTO3 = False
|
HAS_BOTO3 = False
|
||||||
|
@ -19,6 +20,7 @@ except ImportError:
|
||||||
try:
|
try:
|
||||||
from google.auth.transport.requests import AuthorizedSession
|
from google.auth.transport.requests import AuthorizedSession
|
||||||
from google.oauth2 import service_account
|
from google.oauth2 import service_account
|
||||||
|
|
||||||
HAS_GOOGLE_LIBRARIES = True
|
HAS_GOOGLE_LIBRARIES = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_GOOGLE_LIBRARIES = False
|
HAS_GOOGLE_LIBRARIES = False
|
||||||
|
@ -117,16 +119,14 @@ async def post_exit(_):
|
||||||
|
|
||||||
@routes.get('/do_config')
|
@routes.get('/do_config')
|
||||||
async def check_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):
|
async def do_regions(request):
|
||||||
if 'token' in request.query:
|
data = await request.json()
|
||||||
token = request.query['token']
|
token = data.get('token', os.environ.get('DO_API_TOKEN'))
|
||||||
elif 'DO_API_TOKEN' in os.environ:
|
if not token:
|
||||||
token = os.environ['DO_API_TOKEN']
|
|
||||||
else:
|
|
||||||
return web.json_response({'error': 'no token provided'}, status=400)
|
return web.json_response({'error': 'no token provided'}, status=400)
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
|
@ -139,6 +139,13 @@ async def do_regions(request):
|
||||||
return web.json_response(json_body, status=r.status)
|
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')
|
@routes.post('/lightsail_regions')
|
||||||
async def lightsail_regions(request):
|
async def lightsail_regions(request):
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="id_do_token">
|
<label for="id_do_token">
|
||||||
Enter your API token. The token must have read and write permissions
|
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>
|
</label>
|
||||||
<div v-if="ui_token_from_env">
|
<div v-if="ui_token_from_env">
|
||||||
<input
|
<input
|
||||||
|
@ -67,7 +67,7 @@ module.exports = {
|
||||||
return fetch("/do_config")
|
return fetch("/do_config")
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.ok) {
|
if (response.has_secret) {
|
||||||
this.ui_token_from_env = true;
|
this.ui_token_from_env = true;
|
||||||
this.load_regions();
|
this.load_regions();
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,16 @@ module.exports = {
|
||||||
if (this.ui_token_from_env || this.do_token) {
|
if (this.ui_token_from_env || this.do_token) {
|
||||||
this.ui_loading_regions = true;
|
this.ui_loading_regions = true;
|
||||||
this.ui_region_error = null;
|
this.ui_region_error = null;
|
||||||
const url = this.ui_token_from_env ? "/do_regions" : "/do_regions?token=" + this.do_token;
|
const payload = this.ui_token_from_env ? {} : {
|
||||||
fetch(url)
|
token: this.do_token
|
||||||
|
};
|
||||||
|
fetch("/do_regions", {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
})
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
if (r.status === 200) {
|
if (r.status === 200) {
|
||||||
return r.json();
|
return r.json();
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<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 v-if="ui_env_secrets" class="form-text alert alert-success" role="alert">
|
||||||
|
AWS credentials were read from the environment variables
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>
|
<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>
|
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>
|
||||||
|
@ -25,23 +32,12 @@
|
||||||
v-on:blur="load_regions"
|
v-on:blur="load_regions"
|
||||||
v-model="aws_secret_key">
|
v-model="aws_secret_key">
|
||||||
</div>
|
</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>
|
</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"
|
<button class="btn btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
v-on:click="submit"
|
v-on:click="submit"
|
||||||
|
@ -58,48 +54,93 @@ module.exports = {
|
||||||
aws_access_key: null,
|
aws_access_key: null,
|
||||||
aws_secret_key: null,
|
aws_secret_key: null,
|
||||||
region: null,
|
region: null,
|
||||||
lightsail_regions: [],
|
// ui helpoer variables
|
||||||
is_loading: false
|
ui_region_options: [],
|
||||||
|
ui_env_secrets: null,
|
||||||
|
ui_loading_check: false,
|
||||||
|
ui_loading_regions: false,
|
||||||
|
ui_config_error: null,
|
||||||
|
ui_region_error: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
is_valid() {
|
has_secrets() {
|
||||||
return this.aws_access_key && this.aws_secret_key && this.region;
|
return this.ui_env_secrets || (this.aws_access_key && this.aws_secret_key);
|
||||||
},
|
},
|
||||||
is_region_disabled() {
|
is_valid() {
|
||||||
return !(this.aws_access_key && this.aws_secret_key) || this.is_loading;
|
return this.has_secrets && this.region;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created: function() {
|
||||||
|
this.check_config();
|
||||||
|
},
|
||||||
methods: {
|
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() {
|
load_regions() {
|
||||||
if (this.aws_access_key && this.aws_secret_key && this.lightsail_regions.length === 0) {
|
if (this.has_secrets && this.ui_region_options.length === 0) {
|
||||||
this.is_loading = true;
|
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', {
|
fetch('/lightsail_regions', {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify(payload)
|
||||||
aws_access_key: this.aws_access_key,
|
|
||||||
aws_secret_key: this.aws_secret_key
|
|
||||||
})
|
})
|
||||||
|
.then((r) => {
|
||||||
|
if (r.status === 200) {
|
||||||
|
return r.json();
|
||||||
|
}
|
||||||
|
throw new Error(r.status);
|
||||||
})
|
})
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
.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(() => {
|
.finally(() => {
|
||||||
this.is_loading = false;
|
this.ui_loading_regions = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
submit() {
|
submit() {
|
||||||
this.$emit('submit', {
|
let submit_value = {
|
||||||
aws_access_key: this.aws_access_key,
|
|
||||||
aws_secret_key: this.aws_secret_key,
|
|
||||||
region: this.region
|
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>
|
</script>
|
||||||
|
|
Loading…
Add table
Reference in a new issue