Skip to content

Commit 66aae38

Browse files
committed
Added region-select and env secrets to lightsail
1 parent af4728b commit 66aae38

File tree

3 files changed

+128
-72
lines changed

3 files changed

+128
-72
lines changed

app/server.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212

1313
try:
1414
import boto3
15+
1516
HAS_BOTO3 = True
1617
except ImportError:
1718
HAS_BOTO3 = False
1819

1920
try:
2021
from google.auth.transport.requests import AuthorizedSession
2122
from google.oauth2 import service_account
23+
2224
HAS_GOOGLE_LIBRARIES = True
2325
except ImportError:
2426
HAS_GOOGLE_LIBRARIES = False
@@ -117,16 +119,14 @@ async def post_exit(_):
117119

118120
@routes.get('/do_config')
119121
async def check_do_config(_):
120-
return web.json_response({"ok": 'DO_API_TOKEN' in os.environ})
122+
return web.json_response({'has_secret': 'DO_API_TOKEN' in os.environ})
121123

122124

123-
@routes.get('/do_regions')
125+
@routes.post('/do_regions')
124126
async def do_regions(request):
125-
if 'token' in request.query:
126-
token = request.query['token']
127-
elif 'DO_API_TOKEN' in os.environ:
128-
token = os.environ['DO_API_TOKEN']
129-
else:
127+
data = await request.json()
128+
token = data.get('token', os.environ.get('DO_API_TOKEN'))
129+
if not token:
130130
return web.json_response({'error': 'no token provided'}, status=400)
131131

132132
headers = {
@@ -139,6 +139,13 @@ async def do_regions(request):
139139
return web.json_response(json_body, status=r.status)
140140

141141

142+
@routes.get('/aws_config')
143+
async def aws_config(_):
144+
if not HAS_BOTO3:
145+
return web.json_response({'error': 'missing_boto'}, status=400)
146+
return web.json_response({'has_secret': 'AWS_ACCESS_KEY_ID' in os.environ and 'AWS_SECRET_ACCESS_KEY' in os.environ})
147+
148+
142149
@routes.post('/lightsail_regions')
143150
async def lightsail_regions(request):
144151
data = await request.json()
@@ -195,9 +202,9 @@ async def gce_regions(request):
195202
response = AuthorizedSession(
196203
service_account.Credentials.from_service_account_info(
197204
data).with_scopes(
198-
['https://www.googleapis.com/auth/compute'])).get(
199-
'https://www.googleapis.com/compute/v1/projects/{project_id}/regions'.format(
200-
project_id=data['project_id'])
205+
['https://www.googleapis.com/auth/compute'])).get(
206+
'https://www.googleapis.com/compute/v1/projects/{project_id}/regions'.format(
207+
project_id=data['project_id'])
201208
)
202209

203210
return web.json_response(json.loads(response.content))

app/static/provider-do.vue

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div class="form-group">
44
<label for="id_do_token">
55
Enter your API token. The token must have read and write permissions
6-
(<a href="https://cloud.digitalocean.com/settings/api/tokens" target="_blank" rel="noopener noreferrer">https://cloud.digitalocean.com/settings/api/tokens</a>):
6+
<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>
77
</label>
88
<div v-if="ui_token_from_env">
99
<input
@@ -67,7 +67,7 @@ module.exports = {
6767
return fetch("/do_config")
6868
.then(r => r.json())
6969
.then(response => {
70-
if (response.ok) {
70+
if (response.has_secret) {
7171
this.ui_token_from_env = true;
7272
this.load_regions();
7373
}
@@ -80,8 +80,16 @@ module.exports = {
8080
if (this.ui_token_from_env || this.do_token) {
8181
this.ui_loading_regions = true;
8282
this.ui_region_error = null;
83-
const url = this.ui_token_from_env ? "/do_regions" : "/do_regions?token=" + this.do_token;
84-
fetch(url)
83+
const payload = this.ui_token_from_env ? {} : {
84+
token: this.do_token
85+
};
86+
fetch("/do_regions", {
87+
method: 'post',
88+
headers: {
89+
'Content-Type': 'application/json'
90+
},
91+
body: JSON.stringify(payload)
92+
})
8593
.then((r) => {
8694
if (r.status === 200) {
8795
return r.json();

app/static/provider-lightsail.vue

Lines changed: 99 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,43 @@
11
<template>
22
<div>
3-
<div class="form-group">
4-
<label>
5-
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>
6-
<br>
7-
Note: Make sure to use an IAM user with an acceptable policy attached (see <a
8-
href="https://github.com/trailofbits/algo/blob/master/docs/deploy-from-ansible.md" target="_blank" rel="noreferrer noopener" >docs</a>)
9-
</label>
10-
<input
11-
type="text"
12-
class="form-control"
13-
name="aws_access_key"
14-
v-on:blur="load_regions"
15-
v-model="aws_access_key"
16-
/>
3+
<div v-if="ui_config_error && ui_config_error === 'missing_boto'" class="form-text alert alert-danger" role="alert">
4+
Python module "boto3" is missing, please install it to proceed
175
</div>
18-
<div class="form-group">
19-
<label>Enter your AWS Secret Key <a
20-
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>
21-
<input
22-
type="password"
23-
class="form-control"
24-
name="aws_secret_key"
25-
v-on:blur="load_regions"
26-
v-model="aws_secret_key">
6+
<div v-if="ui_env_secrets" class="form-text alert alert-success" role="alert">
7+
AWS credentials were read from the environment variables
278
</div>
28-
<div class="form-group">
29-
<label v-if="lightsail_regions.length === 0">Please enter Access key and Secret key to select region</label>
30-
<label v-if="is_loading">Loading regions...</label>
31-
<label v-if="lightsail_regions.length > 0">What region should the server be located in?</label>
32-
<select name="region"
33-
class="form-control"
34-
v-model="region"
35-
v-bind:disabled="is_region_disabled">
36-
<option value disabled>Select region</option>
37-
<option
38-
v-for="(region, i) in lightsail_regions"
39-
v-bind:key="region.displayName"
40-
v-bind:value="region.name"
41-
>{{region.displayName}}</option>
42-
</select>
43-
9+
<div v-else>
10+
<div class="form-group">
11+
<label>
12+
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>
13+
<br>
14+
Note: Make sure to use an IAM user with an acceptable policy attached (see <a
15+
href="https://github.com/trailofbits/algo/blob/master/docs/deploy-from-ansible.md" target="_blank" rel="noreferrer noopener" >docs</a>)
16+
</label>
17+
<input
18+
type="text"
19+
class="form-control"
20+
name="aws_access_key"
21+
v-on:blur="load_regions"
22+
v-model="aws_access_key"
23+
/>
24+
</div>
25+
<div class="form-group">
26+
<label>Enter your AWS Secret Key <a
27+
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>
28+
<input
29+
type="password"
30+
class="form-control"
31+
name="aws_secret_key"
32+
v-on:blur="load_regions"
33+
v-model="aws_secret_key">
34+
</div>
4435
</div>
36+
<region-select v-model="region"
37+
v-bind:options="ui_region_options"
38+
v-bind:loading="ui_loading_check || ui_loading_regions"
39+
v-bind:error="ui_region_error">
40+
</region-select>
4541
<button class="btn btn-primary"
4642
type="button"
4743
v-on:click="submit"
@@ -58,48 +54,93 @@ module.exports = {
5854
aws_access_key: null,
5955
aws_secret_key: null,
6056
region: null,
61-
lightsail_regions: [],
62-
is_loading: false
57+
// ui helpoer variables
58+
ui_region_options: [],
59+
ui_env_secrets: null,
60+
ui_loading_check: false,
61+
ui_loading_regions: false,
62+
ui_config_error: null,
63+
ui_region_error: null
6364
};
6465
},
6566
computed: {
66-
is_valid() {
67-
return this.aws_access_key && this.aws_secret_key && this.region;
67+
has_secrets() {
68+
return this.ui_env_secrets || (this.aws_access_key && this.aws_secret_key);
6869
},
69-
is_region_disabled() {
70-
return !(this.aws_access_key && this.aws_secret_key) || this.is_loading;
70+
is_valid() {
71+
return this.has_secrets && this.region;
7172
}
7273
},
74+
created: function() {
75+
this.check_config();
76+
},
7377
methods: {
78+
check_config() {
79+
this.ui_loading_check = true;
80+
fetch("/aws_config")
81+
.then(r => {
82+
if (r.status === 200 || r.status === 400) {
83+
return r.json();
84+
}
85+
throw new Error(r.status);
86+
})
87+
.then(response => {
88+
if (response.has_secret) {
89+
this.ui_env_secrets = true;
90+
this.load_regions();
91+
} else if (response.error) {
92+
this.ui_config_error = response.error;
93+
}
94+
})
95+
.finally(() => {
96+
this.ui_loading_check = false;
97+
});
98+
},
7499
load_regions() {
75-
if (this.aws_access_key && this.aws_secret_key && this.lightsail_regions.length === 0) {
76-
this.is_loading = true;
100+
if (this.has_secrets && this.ui_region_options.length === 0) {
101+
this.ui_loading_regions = true;
102+
this.ui_region_error = false;
103+
const payload = this.ui_env_secrets ? {} : {
104+
aws_access_key: this.aws_access_key,
105+
aws_secret_key: this.aws_secret_key
106+
}
77107
fetch('/lightsail_regions', {
78108
method: 'post',
79109
headers: {
80110
'Content-Type': 'application/json'
81111
},
82-
body: JSON.stringify({
83-
aws_access_key: this.aws_access_key,
84-
aws_secret_key: this.aws_secret_key
85-
})
112+
body: JSON.stringify(payload)
113+
})
114+
.then((r) => {
115+
if (r.status === 200) {
116+
return r.json();
117+
}
118+
throw new Error(r.status);
86119
})
87-
.then(r => r.json())
88120
.then(data => {
89-
this.lightsail_regions = data.regions;
121+
this.ui_region_options = data.regions.map(i => ({key: i.name, value: i.displayName}));
122+
})
123+
.catch((err) => {
124+
this.ui_region_error = err;
90125
})
91126
.finally(() => {
92-
this.is_loading = false;
127+
this.ui_loading_regions = false;
93128
});
94129
}
95130
},
96131
submit() {
97-
this.$emit('submit', {
98-
aws_access_key: this.aws_access_key,
99-
aws_secret_key: this.aws_secret_key,
132+
let submit_value = {
100133
region: this.region
101-
});
134+
}
135+
if (!this.ui_env_secrets) {
136+
submit_value['aws_access_key'] = this.aws_access_key;
137+
submit_value['aws_secret_key'] = this.aws_secret_key;
138+
}
139+
this.$emit('submit', submit_value);
102140
}
141+
},
142+
components: {
143+
"region-select": window.httpVueLoader("/static/region-select.vue"),
103144
}
104145
};
105146
</script>

0 commit comments

Comments
 (0)