summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhc <hc@email.ch>2024-09-12 11:46:51 +0800
committerhc <hc@email.ch>2024-09-12 11:46:51 +0800
commitfabefacd8da4932c9a5e8b4aec33d196c290d33b (patch)
tree58f775cff291903a091ed3d4a63265ad44705614
archive of tuffy and btcdashboardHEADmain
-rw-r--r--btcdashboard/App.js81
-rw-r--r--btcdashboard/DOCS/react121
-rw-r--r--btcdashboard/pulltoredis.py56
-rw-r--r--btcdashboard/server3.js43
-rw-r--r--tuffy/tuffycommand1.py379
5 files changed, 580 insertions, 0 deletions
diff --git a/btcdashboard/App.js b/btcdashboard/App.js
new file mode 100644
index 0000000..838ab4f
--- /dev/null
+++ b/btcdashboard/App.js
@@ -0,0 +1,81 @@
1import React, { useState, useEffect } from 'react';
2import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
3
4const App = () => {
5 const [prices, setPrices] = useState([]);
6 const [rawData, setRawData] = useState('');
7 const [error, setError] = useState(null);
8
9 const testingString = "hiiii";
10
11 useEffect(() => {
12 const fetchPrices = async () => {
13 try {
14 console.log('Fetching prices...');
15 const response = await fetch('/api/prices', {
16 method: 'GET',
17 headers: {
18 'Content-Type': 'application/json',
19 },
20 });
21 console.log('Response status:', response.status);
22 console.log('Response headers:', response.headers);
23 if (!response.ok) {
24 throw new Error(`HTTP error! status: ${response.status}`);
25 }
26 const data = await response.json();
27 console.log('Fetched data:', data);
28 setPrices(data);
29 setRawData(JSON.stringify(data, null, 2));
30 setError(null);
31 } catch (error) {
32 console.error('Failed to fetch prices:', error);
33 setError(error.toString());
34 setRawData('');
35 }
36 };
37 fetchPrices();
38 const interval = setInterval(fetchPrices, 5000);
39 return () => clearInterval(interval);
40 }, []);
41
42 // prep data
43 const chartData = prices.map(item => {
44 const parsedItem = JSON.parse(item);
45 return {
46 price: parsedItem.price,
47 time: new Date(parsedItem.timestamp * 1000).toLocaleTimeString()
48 };
49 }).reverse(); // show oldest data first
50
51 return (
52 <div>
53 <h1>price</h1>
54 <p>test stuff: {testingString}</p>
55 {error && <p>Error: {error}</p>}
56 <pre>{rawData}</pre>
57
58 <h2>Price Graph</h2>
59 <ResponsiveContainer width="100%" height={400}>
60 <LineChart
61 data={chartData}
62 margin={{
63 top: 5,
64 right: 30,
65 left: 20,
66 bottom: 5,
67 }}
68 >
69 <CartesianGrid strokeDasharray="3 3" />
70 <XAxis dataKey="time" />
71 <YAxis domain={['auto', 'auto']} />
72 <Tooltip />
73 <Legend />
74 <Line type="monotone" dataKey="price" stroke="#8884d8" activeDot={{ r: 8 }} />
75 </LineChart>
76 </ResponsiveContainer>
77 </div>
78 );
79};
80
81export default App;
diff --git a/btcdashboard/DOCS/react1 b/btcdashboard/DOCS/react1
new file mode 100644
index 0000000..9f8da04
--- /dev/null
+++ b/btcdashboard/DOCS/react1
@@ -0,0 +1,21 @@
1
2sudo dnf update -y
3sudo dnf install nodejs npm -y
4mkdir prices && cd prices
5
6npx create-react-app client
7cd client
8cd ..
9npm install axios recharts
10
11mkdir server
12cd server
13npm init -y
14cd ..
15npm install express redis cors
16
17sudo dnf install -y redis
18sudo systemctl start redis
19sudo systemctl enable redis
20sudo systemctl status redis
21
diff --git a/btcdashboard/pulltoredis.py b/btcdashboard/pulltoredis.py
new file mode 100644
index 0000000..0a82fa7
--- /dev/null
+++ b/btcdashboard/pulltoredis.py
@@ -0,0 +1,56 @@
1import asyncio
2import aiohttp
3import redis
4import json
5import logging
6import time
7
8logging.basicConfig(level=logging.INFO)
9logger = logging.getLogger(__name__)
10
11# redis default port
12redis_client = redis.Redis(host='localhost', port=6379, db=0)
13
14URL = 'https://api.kraken.com/0/public/Ticker?pair=BTCUSD'
15HEADERS = {'Accept': 'application/json'}
16
17MAX_PRICES = 10
18UPDATE_INTERVAL = 3 # seconds
19
20async def fetch_btc_price(session):
21 try:
22 async with session.get(URL, headers=HEADERS, ssl=False) as response:
23 data = await response.json()
24 return float(data['result']['XXBTZUSD']['c'][0])
25 except Exception as e:
26 logger.error(f"error getting price: {e}")
27 return None
28
29async def update_price():
30 async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session:
31 while True:
32 price = await fetch_btc_price(session)
33 if price:
34 timestamp = int(time.time()) # this is unix
35 price_data = json.dumps({"price": price, "timestamp": timestamp})
36
37 redis_client.lpush('btc_prices', price_data)
38
39 redis_client.ltrim('btc_prices', 0, MAX_PRICES - 1)
40
41 logger.info(f"updated btc price: ${price}")
42
43 all_prices = redis_client.lrange('btc_prices', 0, -1)
44 logger.info("prices:")
45 for i, p in enumerate(all_prices, 1):
46 p_data = json.loads(p)
47 logger.info(f"{i}. ${p_data['price']} at {p_data['timestamp']}")
48
49 await asyncio.sleep(UPDATE_INTERVAL)
50
51async def main():
52 logger.info("btc price update")
53 await update_price()
54
55if __name__ == "__main__":
56 asyncio.run(main())
diff --git a/btcdashboard/server3.js b/btcdashboard/server3.js
new file mode 100644
index 0000000..72bfb8d
--- /dev/null
+++ b/btcdashboard/server3.js
@@ -0,0 +1,43 @@
1const express = require('express');
2const cors = require('cors');
3const redis = require('redis');
4
5const app = express();
6const PORT = 3001;
7
8const redisClient = redis.createClient({
9 url: 'redis://localhost:6379' // this is default port
10});
11
12// CORS
13app.use((req, res, next) => {
14 res.header('Access-Control-Allow-Origin', '*');
15 res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
16 res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
17 next();
18});
19
20app.get('/api/prices', async (req, res) => {
21 try {
22 const prices = await redisClient.lRange('btc_prices', 0, -1);
23
24 res.header('Access-Control-Allow-Origin', '*');
25 res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
26 res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
27
28 res.json(prices);
29 } catch (error) {
30 console.error('Error fetching prices:', error);
31 res.status(500).json({ error: 'Internal Server Error' });
32 }
33});
34
35async function startServer() {
36 await redisClient.connect();
37
38 app.listen(PORT, () => {
39 console.log(`Server running on http://localhost:${PORT}`);
40 });
41}
42
43startServer().catch(console.error);
diff --git a/tuffy/tuffycommand1.py b/tuffy/tuffycommand1.py
new file mode 100644
index 0000000..5b069ea
--- /dev/null
+++ b/tuffy/tuffycommand1.py
@@ -0,0 +1,379 @@
1#!/usr/bin/env python3
2import argparse
3import os
4import io
5import os
6import shutil
7import fileinput
8import subprocess
9#import paramiko #install pip3, paramiko, zip
10import sys
11import time
12
13"""
14External dependencies:
15https://api.ipify.org
16 to get the pubic facing ip address of this server
17
18 NOTES
19 -before deploying, make sure template files are present and pub keys installed
20 -at each step of the process, describe what you want to do
21
22 next steps
23 -hardcode aws and terraform installation and their credentials for ease of testing on new servers
24 -can test exfil and infil
25 -
26
27"""
28#global variables
29working_user="ubuntu"
30working_directory=f"/home/{working_user}/tuffycommand1"
31
32def deploy(args):
33 #print(f"Hello {args.name}!")
34 #print(f"{args.name}, {args.cloudcomputeprovider}, {args.location}, {args.serverid}, {args.clients}!")
35
36 #prerequisite for this code block to run is to have the lowpriv pub in the user dir, rest works
37 #this is to initialise the low priv user to put files in.
38 #store the variable 'username' and install ssh keys if they don't exist for remote user login
39 lpusername = "lowpriv"
40 pubkey_file = f"{working_directory}/pubkey/lowpriv.pub"
41
42 file_names = [f"{pubkey_file}",
43 f"{working_directory}/server_exec-template/comp208.pub",
44 f"{working_directory}/server_exec-template/exfil.sh",
45 f"{working_directory}/server_exec-template/init.sh",
46 f"{working_directory}/server_exec-template/lowpriv",
47 f"{working_directory}/server_provisioning-template/template.tf",
48 f"{working_directory}/server_provisioning-template/tf-start.sh",
49 f"{working_directory}/server_provisioning-template/tf-end.sh"]
50 for file_name in file_names:
51 if os.path.exists(file_name):
52 continue
53 else:
54 print("one of the prerequisite files isn't present.")
55 print("exiting program")
56 sys.exit()
57
58 if os.system("grep -q '^" + lpusername + ":' /etc/passwd") == 0:
59 print("user already exist, pub key is assumed to be installed")
60 else:
61 print("user does not exist, creating...")
62 #create the new user with low-privileges!!
63 subprocess.run(["useradd", "-m", "-s", "/bin/bash", lpusername])
64 subprocess.run(["mkdir", "-p", f"/home/{lpusername}/.ssh"])
65 subprocess.run(["chmod", "700", f"/home/{lpusername}/.ssh"])
66 subprocess.run(["touch", f"/home/{lpusername}/.ssh/authorized_keys"])
67 subprocess.run(["chmod", "600", f"/home/{lpusername}/.ssh/authorized_keys"])
68 subprocess.run(["chown", "-R", f"{lpusername}:{lpusername}", f"/home/{lpusername}/.ssh"])
69 with open(pubkey_file, "r") as f:
70 pubkey_file = f.read()
71 with open(f"/home/{lpusername}/.ssh/authorized_keys", "a") as auth_file:
72 auth_file.write(pubkey_file)
73 print(f"User '{lpusername}' has been created with the provided public key")
74
75 cmd = "curl ifconfig.me"
76 result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
77 local_public_ip = result.stdout.decode().strip()
78 print(local_public_ip)
79
80
81 #you need these 3 variables and serverid to configure the template for terraform!
82 location_aws=""
83 ami=""
84 ccp=""
85 if args.location == "London":
86 location_aws = "eu-west-2"
87 ami="ami-038d76c4d28805c09"
88 ccp="aws"
89 elif args.location == "Paris":
90 location_aws = "eu-west-3"
91 ami="ami-0dfb6769e523bf035"
92 ccp="aws"
93 else:
94 print("Error: invalid cloud compute location. Allowed locations are 'London' and 'Paris'")
95 print("exiting program")
96 sys.exit()
97
98 #create unique directory
99 path = os.path.join(working_directory,"instances", args.name, ccp, args.location, args.serverid)
100 print(f"unique server path is {path}")
101 if os.path.exists(os.path.expanduser(path)):
102 print("Error: Directory already exists, nothing will happen, program will continue to run")
103 else:
104 os.makedirs(os.path.expanduser(path))
105 print("hi new directory will be made")
106
107 # copy file from source to destination directory
108 source_dir = f"{working_directory}/server_provisioning-template/"
109 dest_dir = f"{path}/server_provisioning/"
110 if not os.path.exists(dest_dir):
111 #if directory does not exist, create it
112 os.makedirs(dest_dir)
113 for filename in os.listdir(source_dir):
114 src_file = os.path.join(source_dir, filename)
115 dest_file = os.path.join(dest_dir, filename)
116 #overwrite the file if it already exists
117 shutil.copy(src_file, dest_file)
118
119
120 # Replace string in template.tf file
121 filename_template = os.path.join(path, "server_provisioning/template.tf")
122 with fileinput.FileInput(os.path.join(path, filename_template), inplace=True, backup="", mode="r") as file:
123 #these strings are already in the template
124 old_string_location = "LOCATION-TEMPLATE"
125 old_string_ami = "AMI-TEMPLATE"
126 old_string_serverid = "SERVERID-TEMPLATE"
127 #do note the below 3 commands do not work on mac due to a bug in sed
128 #verified it works in linux
129 subprocess.run(f"sed -i 's/{old_string_location}/{location_aws}/g' {filename_template}", shell=True)
130 subprocess.run(f"sed -i 's/{old_string_ami}/{ami}/g' {filename_template}", shell=True)
131 subprocess.run(f"sed -i 's/{old_string_serverid}/{args.serverid}/g' {filename_template}", shell=True)
132 print("template change success")
133
134 #commands to execute in the particular instance's directory
135 print("path changed to the server path")
136 path_server_provisioning=os.path.join(f"{path}","server_provisioning/")
137 os.chdir(path_server_provisioning)
138 commands = [
139 f"chmod +x {path_server_provisioning}tf-start.sh",
140 f"chmod +x {path_server_provisioning}tf-end.sh",
141 f"sudo {path_server_provisioning}tf-start.sh"
142 ]
143
144
145 # Iterate over the commands and execute them
146 for command in commands:
147 # Build the full SSH command to execute
148 #full_command = f"{ssh_command} '{command}'"
149 # Start the subprocess and capture the output
150 process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
151 # Print the output as it is generated
152 while True:
153 # Read a line of output from the process's stdout stream
154 output = process.stdout.readline()
155 # If there is no more output, break out of the loop
156 if not output:
157 break
158 # Decode the output and print it to the console
159 print(output.decode().strip())
160 # Print any error messages that were generated
161 stderr_output = process.stderr.read().decode()
162 if stderr_output:
163 print(f"Error: {stderr_output.strip()}")
164 # Wait for the process to finish
165 process.wait()
166 subprocess.run(f"mv terraform-output.txt ../", shell=True)
167 os.chdir(working_directory)
168
169
170 #after tf-start.sh is executed, output.txt is produced
171 #store each variable of "output.txt"
172 filename_output = os.path.join(path, "terraform-output.txt")
173 instance_id=""
174 instance_public_ip=""
175 instance_labelled_serverid=""
176 with open(filename_output) as file:
177 lines = [line.strip() for line in file.readlines()]
178 instance_id=lines[0]
179 instance_public_ip=lines[1]
180 instance_labelled_serverid=lines[2]
181 #check if the created server id, labelled in terraform is the same as the one given as input. it should be the same.
182 if args.serverid == instance_labelled_serverid:
183 pass
184 print("server initialisation success!!")
185 else:
186 print('ERROR! \nThe instance you created does not have the same server id as the one you assigned it.\n(The problem is due to a mistake made by the programmer)')
187
188
189 print("\nserver initialisation success! now we are going to configure and install the vpn on the server\n")
190
191 #set source and destination directory
192 source_dir = "server_exec-template/"
193 dest_dir = os.path.join(path, "server_exec")
194 if not os.path.exists(dest_dir):
195 #if directory does not exist, create it
196 os.makedirs(dest_dir)
197 #copy all files from the source destination
198 for filename in os.listdir(source_dir):
199 src_file = os.path.join(source_dir, filename)
200 dest_file = os.path.join(dest_dir, filename)
201 #overwrite the file if it already exists
202 shutil.copy(src_file, dest_file)
203
204
205
206
207 #now make the .sh file to be executed in the user environment
208
209 #create edited input file, line seperated
210 with io.open(os.path.expanduser(f"{path}/server-info-all.txt"), "w", encoding="utf-8") as f:
211 f.write(f"{args.name}\n")
212 f.write(f"{ccp}\n")
213 f.write(f"{args.location}\n")
214 f.write(f"{args.clients}\n")
215 f.write(f"{args.serverid}\n")
216 f.write(f"{location_aws}\n")
217 f.write(f"{ami}\n")
218 f.write(f"\n")
219 f.write(f"{local_public_ip}\n")
220 f.write(f"{instance_public_ip}\n")
221 f.write(f"{lpusername}\n")
222 f.write(f"{pubkey_file}\n")
223
224
225
226 #generate a list of client names
227 clients = [f'client{i}' for i in range(1, args.clients+1)]
228 #concatenate the client names into a comma-separated string
229 client_string = ','.join(clients)
230 print(f"client string is {client_string}")
231
232
233 filename_template = os.path.join(f"{path}","server_exec", "exfil.sh")
234 #subprocess.run(f"cat {filename_template}", shell=True)
235 with fileinput.FileInput(os.path.join(path, filename_template), inplace=True, backup="", mode="r") as file:
236 #these strings are already in the template
237 old_string_iip = "instance_ip_TEMPLATE"
238 old_string_clientstring = "allclients_TEMPLATE"
239 old_string_lpusername = "lowpriv_TEMPLATE"
240 old_string_serverip = "exfil_ip_TEMPLATE"
241 lowpriv_serverdir=f"/home/lowpriv{path}"
242 old_string_serverdir = "exfil_dir_TEMPLATE"
243 #do note the below 3 commands do not work on mac due to a bug in sed
244 #verified it works in linux
245 subprocess.run(f"sed -i 's/{old_string_iip}/{instance_public_ip}/g' {filename_template}", shell=True)
246 subprocess.run(f"sed -i 's/{old_string_clientstring}/{client_string}/g' {filename_template}", shell=True)
247 subprocess.run(f"sed -i 's/{old_string_lpusername}/{lpusername}/g' {filename_template}", shell=True)
248 subprocess.run(f"sed -i 's/{old_string_serverip}/{local_public_ip}/g' {filename_template}", shell=True)
249 subprocess.run(f"sed -i 's+{old_string_serverdir}+{lowpriv_serverdir}+g' {filename_template}", shell=True)
250
251
252 #instance_public_ip="10.211.55.18"
253 print("sleeping 10")
254 time.sleep(10)
255 #if not, ssh will fail, aws needs a bit of time for their ssh to work
256 username='ubuntu'
257 key_filename='/home/ubuntu/awscomp208.pem'
258 print(instance_public_ip)
259
260 # make the zipped file from the folder that already contains the preconfigured files first
261 local_folder_name = os.path.join(path, "server_exec")
262 local_zipped_file = f'{local_folder_name}.zip'
263 path_to_zipped_file = os.path.join(path,local_zipped_file)
264 #print("hiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii")
265 #print(path_to_zipped_file)
266 print("zipping local configured initialisation files for transfer")
267 subprocess.run(f"cp {path}/server-info-all.txt {local_folder_name}/", shell=True)
268 subprocess.run(f"zip -r {local_folder_name}.zip {local_folder_name}/", shell=True)
269 print("")
270
271 time.sleep(1)
272 print("transferring zipped file over to the other(vpn) server")
273 #EDIT SSH AUTH FILE AND USERNAME HERE
274 print(local_zipped_file)
275 print(instance_public_ip)
276 subprocess.run(f"scp -i /home/ubuntu/awscomp208.pem -o StrictHostKeyChecking=no {local_zipped_file} ubuntu@{instance_public_ip}:/home/ubuntu/", shell=True)
277 subprocess.run(f"scp -i /home/ubuntu/awscomp208.pem -o StrictHostKeyChecking=no {path}/server_exec/init.sh ubuntu@{instance_public_ip}:/home/ubuntu/", shell=True)
278 # unzip file on remote server
279
280 remote_folder_name = local_folder_name[1:]
281
282 # Define the SSH command to use
283 ssh_command = f"ssh -i {key_filename} {username}@{instance_public_ip}"
284
285 # Define the commands to execute
286 commands = [
287 #f"sudo apt-get update",
288 #f"echo 'update completed, sleeping for 20 seconds'",
289 #f"sleep 20",
290 #f"sudo apt-get install zip unzip tree tmux vim htop mlocate mosh net-tools -y",
291 f"sudo rm -rf /var/lib/apt/lists/*",
292 f"sudo chmod +x init.sh",
293 f"sudo ./init.sh",
294 #f"sudo apt-get update && sudo apt-get install zip unzip tree -y",
295 f"unzip -o /home/ubuntu/server_exec.zip -d /home/ubuntu/",
296 f"cp {remote_folder_name}/* .",
297 f"rm -rf home/ ",
298 f"chmod +x *",
299 f"sudo ./exfil.sh"
300 ]
301
302 # Iterate over the commands and execute them
303 for command in commands:
304 # Build the full SSH command to execute
305 full_command = f"{ssh_command} '{command}'"
306 # Start the subprocess and capture the output
307 process = subprocess.Popen(full_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
308 # Print the output as it is generated
309 while True:
310 # Read a line of output from the process's stdout stream
311 output = process.stdout.readline()
312 # If there is no more output, break out of the loop
313 if not output:
314 break
315 # Decode the output and print it to the console
316 print(output.decode().strip())
317 # Print any error messages that were generated
318 stderr_output = process.stderr.read().decode()
319 if stderr_output:
320 print(f"Error: {stderr_output.strip()}")
321 # Wait for the process to finish
322 process.wait()
323
324 subprocess.run(f"tree /home/lowpriv/", shell=True)
325 #subprocess.run(f"sudo mkdir {path}/files/", shell=True)
326 subprocess.run(f"sudo unzip /home/{lpusername}{path}/t33-exfil.zip -d {path}", shell=True)
327
328
329 path2 = os.path.join("/opt/lampp/htdocs/",args.name, ccp, args.location, args.serverid)
330 if not os.path.exists(path2):
331 os.makedirs(path2, mode=0o777, exist_ok=True)
332 print(path2)
333 subprocess.run(f"sudo mv {path}/t33-exfil/* {path2}", shell=True)
334 subprocess.run("pwd",shell=True)
335 subprocess.run(f"sudo zip -j {path2}/file.zip {path2}/*", shell=True)
336 subprocess.run(f"sudo chmod 777 {path2}/file.zip ", shell=True)
337# subprocess.run(f"sudo rm -rf /home/ubuntu/tuffycommand1/instances/", shell=True)
338 #subprocess.run(f"tree /home/ubuntu/tuffycommand1", shell=True)
339
340
341
342# ssh.close()
343
344
345
346
347
348
349
350
351
352def destroy(args):
353 print(f"currently in development!")
354
355
356if __name__ == '__main__':
357 parser = argparse.ArgumentParser()
358 subparsers = parser.add_subparsers()
359
360 deploy_p = subparsers.add_parser('deploy')
361 deploy_p.add_argument('name')
362 deploy_p.add_argument('cloudcomputeprovider')
363 deploy_p.add_argument('location')
364 deploy_p.add_argument('serverid')
365 deploy_p.add_argument('clients',type=int)
366 deploy_p.set_defaults(func=deploy)
367
368 destroy_p = subparsers.add_parser('destroy')
369 destroy_p.add_argument('name')
370 destroy_p.set_defaults(func=destroy)
371
372 try:
373 args = parser.parse_args()
374 args.func(args)
375 except AttributeError:
376 print("Error: no sub-command specified.")
377 parser.print_help()
378
379