Compare commits

..
33 Commits
Author SHA1 Message Date
IshaVenikar a17386eb68 Update method name to get record by Id
Lint / lint (20.x) (pull_request) Successful in 4m40s
2025-02-03 09:23:03 +05:30
Shreerang Kale f318a95641 Fix custom domain not showing up in UI 2025-02-03 09:23:03 +05:30
Shreerang Kale e9f746cd8b Revert removing order while getting latest DNS data 2025-02-03 09:23:03 +05:30
IshaVenikar e59c14440c Fix check for setting isCurrent 2025-02-03 09:23:03 +05:30
IshaVenikar 22f8a8c943 Update method to return single DNS record by ID 2025-02-03 09:23:03 +05:30
IshaVenikar df5062c75f Remove ununsed imports 2025-02-03 09:23:03 +05:30
Shreerang Kale 22e814840e Fix method to get latest DNS data 2025-02-03 09:23:03 +05:30
IshaVenikar 9d27dd568a Update isCurrent status for commit deployments 2025-02-03 09:23:03 +05:30
Shreerang Kale fc62392c83 Update methods for using stored DNS deployments in UI 2025-02-03 09:23:03 +05:30
IshaVenikar 2ee65b8fd8 Remove ununsed variables 2025-02-03 09:23:03 +05:30
IshaVenikar d0302d0153 Store domain for DNS deployments after previous deployment is deleted 2025-02-03 09:23:03 +05:30
Shreerang Kale 90e9260eb6 Update UI when IP address is unavailable and project is created via auctions 2025-02-03 09:23:03 +05:30
IshaVenikar 6dcee29487 Update flow for deleting deployments 2025-02-03 09:23:03 +05:30
IshaVenikar 5be10b6b0a Implement functionality to store DNS deployment 2025-02-03 09:23:01 +05:30
Shreerang Kale 6e8af82dc2 Make service provider domains non clickable 2025-02-03 09:18:14 +05:30
Shreerang Kale 1a5ab4d47e Remove showing domain status in overview pannel 2025-02-03 09:18:14 +05:30
Shreerang Kale 6df685831f Populate domainId while creating deployment 2025-02-03 09:18:14 +05:30
IshaVenikar 13892015a5 Store DNS deployment records data in Deployment entity 2025-02-03 09:18:14 +05:30
Shreerang Kale 55500b5914 Display custom domain in project card 2025-02-03 09:18:14 +05:30
Shreerang Kale a7190ed804 Show custom domain in overview tabs panel 2025-02-03 09:18:14 +05:30
Shreerang Kale 6a79ee5c47 Remove UI elements for domain verification 2025-02-03 09:18:14 +05:30
Shreerang Kale f2ba931961 Update method to show IP address 2025-02-03 09:18:14 +05:30
IshaVenikar 85b4265fbe Query DNS records by Id 2025-02-03 09:18:14 +05:30
Shreerang Kale 63223a4807 Get DNS records for all completed deployments 2025-02-03 09:18:14 +05:30
Shreerang Kale 9784eb4f4a Fix DNS records data not getting stored in the DB 2025-02-03 09:18:14 +05:30
Shreerang Kale 624f36155a Fix deploy button disabled for deployers with no min payment 2025-02-03 09:18:14 +05:30
IshaVenikar 82c4b71694 Use oldest custom domain in deployment requests 2025-02-03 09:18:14 +05:30
Shreerang Kale 5d9c965f54 Show service provider IP address while creating custom domain 2025-02-03 09:18:14 +05:30
IshaVenikar 56eccb48b3 Add method to fetch DNS data for latest deployment 2025-02-03 09:18:14 +05:30
Shreerang Kale b5762432e6 Remove redirect domain from edit domain form 2025-02-03 09:18:14 +05:30
Shreerang Kale 4ae4670dca Remove redirect domain creation while adding custom domain 2025-02-03 09:18:14 +05:30
IshaVenikar c202554002 Store DNS record data for deployments 2025-02-03 09:18:14 +05:30
nabarunandIshaVenikar 534871a7ae Implement functionality to encrypt environment variables (#48)
Lint / lint (20.x) (push) Successful in 4m45s
Deploy Snowball frontend / deploy (20.x) (push) Successful in 5m1s
Part of https://www.notion.so/Support-encrypted-config-for-deploy-laconic-com-18aa6b22d4728099bc64fc7a310b530d

Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #48
2025-01-30 09:44:18 +00:00
6 changed files with 131 additions and 55 deletions
+1
View File
@@ -27,6 +27,7 @@
"nanoid": "3",
"nanoid-dictionary": "^5.0.0-beta.1",
"octokit": "^3.1.2",
"openpgp": "^6.0.1",
"reflect-metadata": "^0.2.1",
"semver": "^7.6.0",
"toml": "^3.0.0",
+3
View File
@@ -15,6 +15,9 @@ export class Deployer {
@Column('varchar')
baseDomain!: string;
@Column('varchar', { nullable: true})
publicKey!: string | null;
@Column('varchar', { nullable: true })
minimumPayment!: string | null;
+53 -3
View File
@@ -4,6 +4,7 @@ import { DateTime } from 'luxon';
import { Octokit } from 'octokit';
import { inc as semverInc } from 'semver';
import { DeepPartial } from 'typeorm';
import * as openpgp from 'openpgp';
import { Account, DEFAULT_GAS_ESTIMATION_MULTIPLIER, Registry as LaconicRegistry, getGasPrice, parseGasAndFees } from '@cerc-io/registry-sdk';
import { DeliverTxResponse, IndexedTx } from '@cosmjs/stargate';
@@ -246,8 +247,11 @@ export class Registry {
repository: string,
auctionId?: string | null,
lrn: string,
apiUrl: string,
environmentVariables: { [key: string]: string },
dns: string,
requesterAddress: string,
publicKey: string,
payment?: string | null
}): Promise<{
applicationDeploymentRequestId: string;
@@ -261,6 +265,13 @@ export class Registry {
throw new Error(`No record found for ${lrn}`);
}
const hash = await this.generateConfigHash(
data.environmentVariables,
data.requesterAddress,
data.publicKey,
data.apiUrl,
);
// Create record of type ApplicationDeploymentRequest and publish
const applicationDeploymentRequest = {
type: APP_DEPLOYMENT_REQUEST_TYPE,
@@ -271,7 +282,7 @@ export class Registry {
// https://git.vdb.to/cerc-io/laconic-registry-cli/commit/129019105dfb93bebcea02fde0ed64d0f8e5983b
config: JSON.stringify({
env: data.environmentVariables
ref: hash,
}),
meta: JSON.stringify({
note: `Added by Snowball @ ${DateTime.utc().toFormat(
@@ -431,9 +442,9 @@ export class Registry {
}
/**
* Fetch deployment DNS record by Id
* Fetch record by Id
*/
async getDNSRecordById(id: string): Promise<DNSRecord[]> {
async getRecordById(id: string): Promise<any[]> {
return this.registry.getRecordsByIds([id]);
}
@@ -538,4 +549,43 @@ export class Registry {
assert(this.registryConfig.authority, "Authority doesn't exist");
return `lrn://${this.registryConfig.authority}/applications/${appName}`;
}
async generateConfigHash(
environmentVariables: { [key: string]: string },
requesterAddress: string,
pubKey: string,
url: string,
): Promise<string> {
// Config to be encrypted
const config = {
authorized: [requesterAddress],
config: { env: environmentVariables },
};
// Serialize the config
const serialized = JSON.stringify(config, null, 2);
const armoredKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n${pubKey}\n\n-----END PGP PUBLIC KEY BLOCK-----`;
const publicKey = await openpgp.readKey({ armoredKey });
// Encrypt the config
const encrypted = await openpgp.encrypt({
message: await openpgp.createMessage({ text: serialized }),
encryptionKeys: publicKey,
format: 'binary',
});
// Get the hash after uploading encrypted config
const response = await fetch(`${url}/upload/config`, {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
},
body: encrypted,
});
const configHash = await response.json();
return configHash.id;
}
}
+68 -51
View File
@@ -22,6 +22,7 @@ import {
AppDeploymentRemovalRecord,
AuctionParams,
DeployerRecord,
DNSRecord,
DNSRecordAttributes,
EnvironmentVariables,
GitPushEventPayload,
@@ -200,61 +201,61 @@ export class Service {
if (!deployment.project) {
log(`Project ${deployment.projectId} not found`);
return;
} else {
const dnsRecord = (await this.laconicRegistry.getDNSRecordById(record.attributes.dns))[0];
}
const dnsRecordData: DNSRecordAttributes = {
name: dnsRecord.attributes.name,
request: dnsRecord.attributes.request,
resourceType: dnsRecord.attributes.resourceType,
value: dnsRecord.attributes.value,
version: dnsRecord.attributes.version,
}
const dnsRecord: DNSRecord = (await this.laconicRegistry.getRecordById(record.attributes.dns))[0];
deployment.applicationDeploymentRecordId = record.id;
deployment.applicationDeploymentRecordData = record.attributes;
deployment.url = record.attributes.url;
deployment.status = DeploymentStatus.Ready;
deployment.isCurrent = deployment.environment === Environment.Production;
deployment.dnsRecordData = dnsRecordData;
const dnsRecordData: DNSRecordAttributes = {
name: dnsRecord.attributes.name,
request: dnsRecord.attributes.request,
resourceType: dnsRecord.attributes.resourceType,
value: dnsRecord.attributes.value,
version: dnsRecord.attributes.version,
}
if (deployment.isDNS) {
// Delete previous DNS deployment
const oldDNSDeployment = await this.db.getDeployment({
where: {
projectId: deployment.project.id,
deployer: deployment.deployer,
isDNS: true,
isCurrent: true,
}
});
deployment.applicationDeploymentRecordId = record.id;
deployment.applicationDeploymentRecordData = record.attributes;
deployment.url = record.attributes.url;
deployment.status = DeploymentStatus.Ready;
deployment.isCurrent = deployment.environment === Environment.Production;
deployment.dnsRecordData = dnsRecordData;
if (oldDNSDeployment) {
await this.db.deleteDeploymentById(oldDNSDeployment.id);
if (oldDNSDeployment.domain) {
await this.db.updateDeploymentById(deployment.id, { domain: oldDNSDeployment.domain })
}
if (deployment.isDNS) {
// Delete previous DNS deployment
const oldDNSDeployment = await this.db.getDeployment({
where: {
projectId: deployment.project.id,
deployer: deployment.deployer,
isDNS: true,
isCurrent: true,
}
});
if (oldDNSDeployment) {
await this.db.deleteDeploymentById(oldDNSDeployment.id);
if (oldDNSDeployment.domain) {
await this.db.updateDeploymentById(deployment.id, { domain: oldDNSDeployment.domain })
}
}
await this.db.updateDeploymentById(deployment.id, deployment);
// Release deployer funds on successful deployment
if (!deployment.project.fundsReleased) {
const fundsReleased = await this.releaseDeployerFundsByProjectId(deployment.projectId);
// Return remaining amount to owner
await this.returnUserFundsByProjectId(deployment.projectId, true);
await this.db.updateProjectById(deployment.projectId, {
fundsReleased,
});
}
log(
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`,
);
}
await this.db.updateDeploymentById(deployment.id, deployment);
// Release deployer funds on successful deployment
if (!deployment.project.fundsReleased) {
const fundsReleased = await this.releaseDeployerFundsByProjectId(deployment.projectId);
// Return remaining amount to owner
await this.returnUserFundsByProjectId(deployment.projectId, true);
await this.db.updateProjectById(deployment.projectId, {
fundsReleased,
});
}
log(
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`,
);
});
await Promise.all(deploymentUpdatePromises);
@@ -684,6 +685,7 @@ export class Service {
const deployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, false);
const dnsDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, true);
const address = await this.getAddress();
const { repo, repoUrl } = await getRepoDetails(octokit, data.project.repository, data.commitHash);
const environmentVariablesObj = await this.getEnvVariables(data.project!.id!);
@@ -702,8 +704,11 @@ export class Service {
environmentVariables: environmentVariablesObj,
dns: domain?.name ?? `${dnsDeployment.project.name}`,
lrn: deployer!.deployerLrn!,
apiUrl: deployer!.deployerApiUrl!,
payment: data.project.txHash,
auctionId: data.project.auctionId
auctionId: data.project.auctionId,
requesterAddress: address,
publicKey: deployer!.publicKey!
});
await this.db.updateDeploymentById(dnsDeployment.id, {
@@ -719,10 +724,13 @@ export class Service {
appName: repo,
repository: repoUrl,
lrn: deployer!.deployerLrn!,
apiUrl: deployer!.deployerApiUrl!,
environmentVariables: environmentVariablesObj,
dns: `${deployment.project.name}-${deployment.id}`,
payment: data.project.txHash,
auctionId: data.project.auctionId
auctionId: data.project.auctionId,
requesterAddress: address,
publicKey: deployer!.publicKey!
});
await this.db.updateDeploymentById(deployment.id, {
@@ -775,6 +783,7 @@ export class Service {
const deployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData, false);
const dnsDeployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData, true);
const address = await this.getAddress();
const environmentVariablesObj = await this.getEnvVariables(project!.id!);
// To set project DNS
@@ -790,6 +799,9 @@ export class Service {
dns: `${dnsDeployment.project.name}`,
auctionId: project.auctionId!,
lrn: deployerLrn,
apiUrl: deployer!.deployerApiUrl!,
requesterAddress: address,
publicKey: deployer!.publicKey!
});
await this.db.updateDeploymentById(dnsDeployment.id, {
@@ -806,8 +818,11 @@ export class Service {
repository: repoUrl,
auctionId: project.auctionId!,
lrn: deployerLrn,
apiUrl: deployer!.deployerApiUrl!,
environmentVariables: environmentVariablesObj,
dns: `${deployment.project.name}-${deployment.id}`,
requesterAddress: address,
publicKey: deployer!.publicKey!
});
await this.db.updateDeploymentById(deployment.id, {
@@ -1500,6 +1515,7 @@ export class Service {
const deployerApiUrl = record.attributes.apiUrl;
const minimumPayment = record.attributes.minimumPayment;
const paymentAddress = record.attributes.paymentAddress;
const publicKey = record.attributes.publicKey;
const baseDomain = deployerApiUrl.substring(deployerApiUrl.indexOf('.') + 1);
const deployerData = {
@@ -1508,7 +1524,8 @@ export class Service {
deployerApiUrl,
baseDomain,
minimumPayment,
paymentAddress
paymentAddress,
publicKey
};
// TODO: Update deployers table in a separate job
@@ -10,7 +10,7 @@ import { Deployment, DeploymentStatus, Environment } from '../src/entity/Deploym
const log = debug('snowball:publish-deploy-records');
async function main() {
const { registryConfig, database, misc } = await getConfig();
const { registryConfig, database } = await getConfig();
const registry = new Registry(
registryConfig.gqlEndpoint,
+5
View File
@@ -14407,6 +14407,11 @@ open@^8.0.4, open@^8.4.0:
is-docker "^2.1.1"
is-wsl "^2.2.0"
openpgp@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/openpgp/-/openpgp-6.0.1.tgz#ab3a2c08a3e23ac7f85c4fc62a3e715d50dc08fb"
integrity sha512-3lReDKjgWsKFArZT4Y/yj7/Q0q6/VhXarn4WqKEkyiBWckNjrThSGoB1t0IKo3Ke0ClvBpyQfTwumkGUkxOwww==
optimism@^0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.0.tgz#e7bb38b24715f3fdad8a9a7fc18e999144bbfa63"