Untitled
unknown
plain_text
2 years ago
11 kB
7
Indexable
const clientId = '746239575955-c4d2o1ahg4ts6ahm3a5lh5lp9g8m15h4.apps.googleusercontent.com'; const clientSecret = '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'; const refreshToken = ''; const service_account = true const service_account_json = { "type": "service_account", "project_id": "gcp-web-bill", "private_key_id": "2ffeb836b95626dc159e7656fa1a4a9b79b986f4", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCT7lBxMBMGXYF4\n4zOTNYDPxSEeHS42ruGRq2u8OvusgJl92WOwvMQpAMC/2v67fZpqKIeC87H9sR7n\nBsbOWX92dF5RQB4kbiZRR2tu9eaK2TAXrKeRdC8dp7Iv/6k0M5wAnkJmOUWLkZYO\nen2xM95HmCcWF3MSgq9kyuqouLL7EBEcFdT6j3lz2wyLEMt4u4h17/NH5kfEdmjF\n+hG/Jk0cAyE/vdcY2m7dH6rG+1utp75Ft9ZQUX/hVzxo5d5Xmmexx4qz63FmzSAh\nHRHi8xxyRuAzIYpbVJzcqlPTp1wqpvF2AE4yKynNBGmcfJz0duG/zndESy2W93xw\nnUUdE5mlAgMBAAECggEACpDBEJB7L19yzZhGmPs/h7df4ed6I0AyzqVkZLV+v6eQ\nrucdomQdC4OpAJrqyifSpUXfRdhTbFff6ea3QMouGx79FIcEkBwI4xG7h9mKvXx9\nHZfAgRg//Dl7tcdoBZkxCW9ENUpeX/VGNyMDAqq+c7UXh5Glr5sDXWrLv0Cv0dQM\nUlnSYjWIaqK2gV+t0DRr21vkZFvDKVTEVQFgWM0T+O736j4u63Ghw0llUs4h7fB9\nMluJx/61LdJShhto750Rj720AS/ZTDSlmXGn5dYO8nBxPO0IAiIklv+IYDZrXMX+\nU6/Lr1VbEUL9zHHfrKxSLLMHVUy5/SurpbGPNqMzSQKBgQDQ/1KMYkSVr//+l1Tx\nkPeXA2OG8djDN0uXZ+SpvLSkWeEXw2VjP9qQ6CHH/j2cR5beuflP4OCZhnDVblum\ns/5uZs42H62T2iXlpR01y2NHFM/OJOKoHu/MkwR6YxmtM6CsuoIdbA/86Qx4R0y/\n2DxvSoB9+07t9sWNq9fgw+1RKQKBgQC1MzFBrLX/Tpa5ArIXk7faUyDDAmgPN9Z8\nxXQ1nWCKD9AI2F+NuUZ2lGkXC4zMj9dpZ9p3F6WrDbc5oQ243I6iDkPSPXsNlGwr\n8epR2DQV7eK44yywRAPcFGz9e2TIiV/uQRzYeub9qE9WXcAiihBer5hhbaAzG13Y\nwzN3A8soHQKBgA6oGS3nJlApC5bbHgXi2LoqbqxkAYOPOSnhC1Qr+68a7oIwHcgc\nDkPjQ5s25TM0ggwUlrtXVejuWLNfDeZe8RTk+Mkq541a2xWDwsym+stdVkVqqMqJ\ngN+j38iFcqOG31m9qqpNjcF6xnkY5vT9QR+85c3v9dUSXUBWMMl+dAIhAoGBAKYW\nWVTQYTW2LFNC1EjmHoRg48u7nfQtA030kxM9wKpr2gzxf4xhQeQZHsZ/0LwEMLet\n+MJmi3ThqouJQxGqIJcMKkBAGFWXMRuKr3P7j6p2FPXRTTn37e3BTzF89CEYQjUZ\nu7310Vq59pa8cgt2r5CKtUrAeDHAKOIx8i9p68JFAoGAfUsqAQgrIDYDMpmSgwo9\nYBALum6m9FjPw3GCqIEPq7WS9rHKe4TWLWT1h9GMJ3j6Tq5GNCvIan9q/k9lmpWS\nJWD8uwgeY5u/EByVlE2sHzFNGWkhUEjJwLPNlOE1hScYfb8b8c3YDixJKVMLvx+G\nV5KDunuVaU5MECrqQW7SoAM=\n-----END PRIVATE KEY-----\n", "client_email": "gcp-web-billing-hook@gcp-web-bill.iam.gserviceaccount.com", "client_id": "113565551544602521875", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gcp-web-billing-hook%40gcp-web-bill.iam.gserviceaccount.com", "universe_domain": "googleapis.com" } var billing_ids = [{ "name": "GCP Main Billing", "id": "01924B-D2C7F3-5DE8E7" } ] const html = `<!DOCTYPE html> <html> <head> <title>GCP Server Current State</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@4/dist/flatly/bootstrap.min.css"> </head> <body> <header> <nav class="navbar navbar-dark bg-dark navbar-expand-lg"> <a href="/" class="navbar-brand d-flex align-items-center"> <img src="https://images.cdn.hashhackers.com/logo/logo-white-d.svg" class="btn1" width="220" height="40"> </a> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav "> </ul> </div> </nav> </header> <div class="container mt-5 mb-5"> <marquee>Web services which are inactive need not to be reported, they'll be back online in a time frame of 24 to 48 hours.</marquee> <ul id="billing-list" class="list-group"> <li class="list-group-item active text-center">Billing Status</li> <!-- JavaScript code will populate the rest of the list --> </ul> </div> <!-- Bootstrap JavaScript --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.9.3/umd/popper.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script> <script> const billing_ids = ` + billing_ids.length + `; const billing_names = ${JSON.stringify(billing_ids.map(billing => billing.name))} // Generate an array of numbers from 0 to billing_ids - 1 const indexArray = Array.from({ length: billing_ids }, (_, i) => i); // Loop through the indexArray and send requests to the API endpoint using each number as an index for (const index of indexArray) { const listItem = $('<li class="text-wrap">').addClass('list-group-item d-flex justify-content-between align-items-center'); const nameSpan = $('<span class="d-inline-block text-break">').text(billing_names[index]).appendTo(listItem); const statusSpan = $('<span>').text('Checking...').addClass('badge badge-secondary').appendTo(listItem); // Send a request to the API endpoint with the current index and set the status badge $.getJSON('/'+index, (data) => { if (data.status == 'invalid') { statusSpan.text('API Error').addClass('badge-info').removeClass('badge-secondary'); } else if (data.status) { statusSpan.text('Active').addClass('badge-success').removeClass('badge-secondary'); } else { statusSpan.text('Inactive').addClass('badge-danger').removeClass('badge-secondary'); } }); $('#billing-list').append(listItem); } </script> </body> </html>` async function handleRequest(request) { let requrl = new URL(request.url); let path = requrl.pathname; if (path == '/') { return new Response(html, { status: 200, headers: { "content-type": "text/html;", "Access-Control-Allow-Origin": "*", } }); } let billingAccountId = path.slice(1); const accessToken = await fetchAccessToken(); // Build the API request URL const url = 'https://cloudbilling.googleapis.com/v1/billingAccounts/' + billing_ids[billingAccountId].id; // Send the API request to check if the billing account is active const response = await fetch(url, { headers: { Authorization: `Bearer ${accessToken}` } }); var text = await response.text() if (!response.ok) { return new Response('{"status":"invalid"}', { status: 200, headers: { "content-type": "application/json;", "Access-Control-Allow-Origin": "*", } }); } const data = JSON.parse(text);; // Check if the billing account is active const billingEnabled = data.open; // Return a response based on whether the billing account is active or not if (billingEnabled) { return new Response('{"status":' + billingEnabled + '}', { status: 200, headers: { "content-type": "application/json;", "Access-Control-Allow-Origin": "*", } }); } else { let json = { chat_id: "513611281", text: "Web Service Offline: " + billing_ids[billingAccountId].name, } await fetch("https://api.telegram.org/bot929918166:AAFbDTrQZASGrcmyuplm3Sw4ym-dAv4EKac/SendMessage", { method: "POST", headers: { 'content-type': 'application/json', }, body: JSON.stringify(json) }); return new Response('{"status":' + billingEnabled + '}', { status: 200, headers: { "content-type": "application/json;", "Access-Control-Allow-Origin": "*", } }); } } async function fetchAccessToken() { const url = "https://oauth2.googleapis.com/token"; const headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; var post_data; if (service_account) { console.log('Service Account') const jwttoken = await JSONWebToken.generateGCPToken(service_account_json); post_data = { grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: jwttoken, }; } else { console.log('Refresh Token') post_data = { client_id: clientId, client_secret: clientSecret, refresh_token: refreshToken, grant_type: "refresh_token", }; } let requestOption = { 'method': 'POST', 'headers': headers, 'body': await enQuery(post_data) }; let response; for (let i = 0; i < 3; i++) { response = await fetch(url, requestOption); if (response.ok) { break; } await this.sleep(800 * (i + 1)); } const data = await response.json(); return data.access_token; } const JSONWebToken = { header: { alg: 'RS256', typ: 'JWT' }, importKey: async function(pemKey) { var pemDER = this.textUtils.base64ToArrayBuffer(pemKey.split('\n').map(s => s.trim()).filter(l => l.length && !l.startsWith('---')).join('')); return crypto.subtle.importKey('pkcs8', pemDER, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['sign']); }, createSignature: async function(text, key) { const textBuffer = this.textUtils.stringToArrayBuffer(text); return crypto.subtle.sign('RSASSA-PKCS1-v1_5', key, textBuffer) }, generateGCPToken: async function(serviceAccount) { const iat = parseInt(Date.now() / 1000); var payload = { "iss": serviceAccount.client_email, "scope": "https://www.googleapis.com/auth/cloud-billing", "aud": "https://oauth2.googleapis.com/token", "exp": iat + 3600, "iat": iat }; const encPayload = btoa(JSON.stringify(payload)); const encHeader = btoa(JSON.stringify(this.header)); var key = await this.importKey(serviceAccount.private_key); var signed = await this.createSignature(encHeader + "." + encPayload, key); return encHeader + "." + encPayload + "." + this.textUtils.arrayBufferToBase64(signed).replace(/\//g, '_').replace(/\+/g, '-'); }, textUtils: { base64ToArrayBuffer: function(base64) { var binary_string = atob(base64); var len = binary_string.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes.buffer; }, stringToArrayBuffer: function(str) { var len = str.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = str.charCodeAt(i); } return bytes.buffer; }, arrayBufferToBase64: function(buffer) { let binary = ''; let bytes = new Uint8Array(buffer); let len = bytes.byteLength; for (let i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } } }; function enQuery(data) { const ret = []; for (let d in data) { ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d])); } return ret.join('&'); } function sleep(ms) { return new Promise(function(resolve, reject) { let i = 0; setTimeout(function() { //console.log('sleep' + ms); i++; if (i >= 2) reject(new Error('i>=2')); else resolve(i); }, ms); }) } addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) })
Editor is loading...