@highstate/common 0.7.8 → 0.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97,7 +97,13 @@ function generatePassword() {
97
97
  }
98
98
 
99
99
  // src/shared/ssh.ts
100
- import { getUnitInstanceName } from "@highstate/pulumi";
100
+ import {
101
+ getOrCreateSecret,
102
+ getUnitInstanceName,
103
+ output as output3
104
+ } from "@highstate/pulumi";
105
+ import getKeys, { PrivateExport } from "micro-key-producer/ssh.js";
106
+ import { randomBytes as randomBytes2 } from "micro-key-producer/utils.js";
101
107
  function createSshTerminal(server) {
102
108
  const command = ["ssh", "-tt", "-o", "StrictHostKeyChecking=no"];
103
109
  if (server.sshCredentials?.port) {
@@ -127,12 +133,36 @@ function createSshTerminal(server) {
127
133
  }
128
134
  };
129
135
  }
136
+ function generatePrivateKey() {
137
+ const seed = randomBytes2(32);
138
+ return getKeys(seed).privateKey;
139
+ }
140
+ function getKeysFromString(privateKey) {
141
+ const privateKeyStruct = PrivateExport.decode(privateKey);
142
+ const privKey = privateKeyStruct.keys[0].privKey.privKey;
143
+ return getKeys(privKey.slice(0, 32));
144
+ }
145
+ function getOrCreateSshKeyPair(inputs, secrets) {
146
+ if (inputs.sshKeyPair) {
147
+ return output3(inputs.sshKeyPair);
148
+ }
149
+ const privateKey = getOrCreateSecret(secrets, "sshPrivateKey", generatePrivateKey);
150
+ const keys = privateKey.apply(getKeysFromString);
151
+ return output3({
152
+ type: "ed25519",
153
+ privateKey,
154
+ publicKey: keys.publicKey
155
+ });
156
+ }
130
157
 
131
158
  export {
132
159
  getServerConnection,
133
160
  Server,
134
161
  DnsRecord,
135
162
  generatePassword,
136
- createSshTerminal
163
+ createSshTerminal,
164
+ generatePrivateKey,
165
+ getKeysFromString,
166
+ getOrCreateSshKeyPair
137
167
  };
138
- //# sourceMappingURL=chunk-M5AC7PLD.js.map
168
+ //# sourceMappingURL=chunk-ITZRY7W5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/server.ts","../src/shared/dns.ts","../../../node_modules/remeda/dist/chunk-D6FCK2GA.js","../../../node_modules/remeda/dist/chunk-WIMGWYZL.js","../../../node_modules/remeda/dist/chunk-VG2NVNXT.js","../src/shared/passwords.ts","../src/shared/ssh.ts"],"sourcesContent":["import { remote, type types } from \"@pulumi/command\"\nimport { output, Resource, type Input, type InputOrArray, type Output } from \"@highstate/pulumi\"\nimport { common } from \"@highstate/library\"\n\nexport function getServerConnection(\n server: Input<common.Server>,\n): Output<types.input.remote.ConnectionArgs> {\n return output(server).apply(server => ({\n host: server.endpoint,\n port: server.sshCredentials?.port ?? 22,\n user: server.sshCredentials?.user ?? \"root\",\n password: server.sshCredentials?.password,\n privateKey: server.sshCredentials?.privateKey,\n dialErrorLimit: 3,\n }))\n}\n\nexport interface CommandOptions {\n id: string\n create: Input<string>\n update?: Input<string>\n delete?: Input<string>\n dependsOn?: InputOrArray<Resource>\n}\n\nexport class Server {\n public readonly server: Output<common.Server>\n public readonly connection: Output<types.input.remote.ConnectionArgs>\n\n public get endpoint(): Output<string> {\n return this.server.endpoint\n }\n\n public get hostname(): Output<string> {\n return this.server.hostname\n }\n\n constructor(server: Input<common.Server>) {\n this.server = output(server)\n this.connection = getServerConnection(this.server)\n }\n\n public command(options: CommandOptions): remote.Command {\n return new remote.Command(\n options.id,\n {\n connection: this.connection,\n create: options.create,\n update: options.update,\n delete: options.delete,\n },\n { dependsOn: options.dependsOn },\n )\n }\n}\n","import type { dns } from \"@highstate/library\"\nimport {\n ComponentResource,\n output,\n Output,\n Resource,\n type Input,\n type ResourceOptions,\n type Unwrap,\n} from \"@highstate/pulumi\"\nimport { capitalize } from \"remeda\"\n\nexport type DnsRecordArgs = {\n /**\n * The DNS provider to use.\n */\n provider: Input<dns.Provider>\n\n /**\n * The name of the DNS record.\n * If not provided, the name of the resource will be used.\n */\n name?: Input<string>\n\n /**\n * The type of the DNS record.\n */\n type: Input<string>\n\n /**\n * The value of the DNS record.\n */\n value: Input<string>\n\n /**\n * Whether the DNS record is proxied (e.g. to provide DDoS protection).\n *\n * Available only for public IPs and some DNS providers like Cloudflare.\n * If not supported, the DNS provider will ignore this value.\n */\n proxied?: Input<boolean>\n}\n\nexport abstract class DnsRecord extends ComponentResource {\n /**\n * The underlying dns record resource.\n */\n public readonly dnsRecord: Output<Resource>\n\n constructor(name: string, args: DnsRecordArgs, opts?: ResourceOptions) {\n super(\"highstate:common:DnsRecord\", name, args, opts)\n\n this.dnsRecord = output(args).apply(args => {\n return output(this.create(name, args, { ...opts, parent: this }))\n })\n\n this.registerOutputs({ dnsRecord: this.dnsRecord })\n }\n\n protected abstract create(\n name: string,\n args: Unwrap<DnsRecordArgs>,\n opts?: ResourceOptions,\n ): Input<Resource>\n\n static create(name: string, args: DnsRecordArgs, opts?: ResourceOptions): Output<DnsRecord> {\n return output(args).apply(async args => {\n const providerType = args.provider.type\n const implName = `${capitalize(providerType)}DnsRecord`\n const implModule = (await import(`@highstate/${providerType}`)) as Record<string, unknown>\n\n const implClass = implModule[implName] as new (\n name: string,\n args: Unwrap<DnsRecordArgs>,\n opts?: ResourceOptions,\n ) => DnsRecord\n\n return new implClass(name, args, opts)\n })\n }\n}\n","function u(o,n,a){let t=r=>o(r,...n);return a===void 0?t:Object.assign(t,{lazy:a,lazyArgs:n})}export{u as a};\n","import{a as t}from\"./chunk-D6FCK2GA.js\";function u(r,n,o){let a=r.length-n.length;if(a===0)return r(...n);if(a===1)return t(r,n,o);throw new Error(\"Wrong number of arguments\")}export{u as a};\n","import{a as i}from\"./chunk-WIMGWYZL.js\";function n(...t){return i(e,t)}var e=t=>`${t[0]?.toUpperCase()??\"\"}${t.slice(1)}`;export{n as a};\n","import { randomBytes } from \"@noble/hashes/utils\"\nimport { secureMask } from \"micro-key-producer/password.js\"\n\nexport function generatePassword() {\n return secureMask.apply(randomBytes(32)).password\n}\n","import type { common, ssh } from \"@highstate/library\"\nimport {\n getOrCreateSecret,\n getUnitInstanceName,\n output,\n Output,\n type Input,\n type InstanceTerminal,\n} from \"@highstate/pulumi\"\nimport getKeys, { PrivateExport } from \"micro-key-producer/ssh.js\"\nimport { randomBytes } from \"micro-key-producer/utils.js\"\n\nexport function createSshTerminal(server: common.Server): InstanceTerminal {\n const command = [\"ssh\", \"-tt\", \"-o\", \"StrictHostKeyChecking=no\"]\n\n if (server.sshCredentials?.port) {\n command.push(\"-p\", server.sshCredentials.port.toString())\n }\n\n if (server.sshCredentials?.privateKey) {\n command.push(\"-i\", \"/private-key\")\n }\n\n const endpoint = server.sshCredentials?.endpoint ?? server.endpoint\n const user = server.sshCredentials?.user ?? \"root\"\n\n command.push(`${user}@${endpoint}`)\n\n if (server.sshCredentials?.password) {\n command.unshift(\"sshpass\", \"-f\", \"/password\")\n }\n\n return {\n name: \"ssh\",\n title: `SSH: ${getUnitInstanceName()}`,\n description: \"Connect to the server via SSH\",\n image: \"ghcr.io/exeteres/highstate/terminal-ssh\",\n command,\n\n files: {\n \"/password\": server.sshCredentials?.password,\n\n \"/private-key\": {\n content: server.sshCredentials?.privateKey,\n mode: 0o600,\n },\n },\n }\n}\n\nexport function generatePrivateKey(): string {\n const seed = randomBytes(32)\n\n return getKeys(seed).privateKey\n}\n\nexport function getKeysFromString(privateKey: string) {\n const privateKeyStruct = PrivateExport.decode(privateKey)\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const privKey = privateKeyStruct.keys[0].privKey.privKey as Uint8Array\n\n return getKeys(privKey.slice(0, 32))\n}\n\nexport type SshKeyPairInputs = {\n sshKeyPair?: Input<ssh.KeyPair>\n}\n\nexport type SshKeyPairSecrets = {\n sshPrivateKey?: Input<string>\n}\n\nexport function getOrCreateSshKeyPair(\n inputs: SshKeyPairInputs,\n secrets: Output<SshKeyPairSecrets>,\n): Output<ssh.KeyPair> {\n if (inputs.sshKeyPair) {\n return output(inputs.sshKeyPair)\n }\n\n const privateKey = getOrCreateSecret(secrets, \"sshPrivateKey\", generatePrivateKey)\n const keys = privateKey.apply(getKeysFromString)\n\n return output({\n type: \"ed25519\",\n privateKey,\n publicKey: keys.publicKey,\n })\n}\n"],"mappings":";AAAA,SAAS,cAA0B;AACnC,SAAS,cAAoE;AAC7E,OAAuB;AAEhB,SAAS,oBACd,QAC2C;AAC3C,SAAO,OAAO,MAAM,EAAE,MAAM,CAAAA,aAAW;AAAA,IACrC,MAAMA,QAAO;AAAA,IACb,MAAMA,QAAO,gBAAgB,QAAQ;AAAA,IACrC,MAAMA,QAAO,gBAAgB,QAAQ;AAAA,IACrC,UAAUA,QAAO,gBAAgB;AAAA,IACjC,YAAYA,QAAO,gBAAgB;AAAA,IACnC,gBAAgB;AAAA,EAClB,EAAE;AACJ;AAUO,IAAM,SAAN,MAAa;AAAA,EACF;AAAA,EACA;AAAA,EAEhB,IAAW,WAA2B;AACpC,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAW,WAA2B;AACpC,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,YAAY,QAA8B;AACxC,SAAK,SAAS,OAAO,MAAM;AAC3B,SAAK,aAAa,oBAAoB,KAAK,MAAM;AAAA,EACnD;AAAA,EAEO,QAAQ,SAAyC;AACtD,WAAO,IAAI,OAAO;AAAA,MAChB,QAAQ;AAAA,MACR;AAAA,QACE,YAAY,KAAK;AAAA,QACjB,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA,MAClB;AAAA,MACA,EAAE,WAAW,QAAQ,UAAU;AAAA,IACjC;AAAA,EACF;AACF;;;ACrDA;AAAA,EACE;AAAA,EACA,UAAAC;AAAA,OAMK;;;ACTP,SAAS,EAAE,GAAEC,IAAE,GAAE;AAAC,MAAI,IAAE,OAAG,EAAE,GAAE,GAAGA,EAAC;AAAE,SAAO,MAAI,SAAO,IAAE,OAAO,OAAO,GAAE,EAAC,MAAK,GAAE,UAASA,GAAC,CAAC;AAAC;;;ACArD,SAASC,GAAE,GAAEC,IAAE,GAAE;AAAC,MAAI,IAAE,EAAE,SAAOA,GAAE;AAAO,MAAG,MAAI,EAAE,QAAO,EAAE,GAAGA,EAAC;AAAE,MAAG,MAAI,EAAE,QAAO,EAAE,GAAEA,IAAE,CAAC;AAAE,QAAM,IAAI,MAAM,2BAA2B;AAAC;;;ACAvI,SAAS,KAAK,GAAE;AAAC,SAAOC,GAAE,GAAE,CAAC;AAAC;AAAC,IAAI,IAAE,OAAG,GAAG,EAAE,CAAC,GAAG,YAAY,KAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;;;AH2ChH,IAAe,YAAf,cAAiC,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAIxC;AAAA,EAEhB,YAAY,MAAc,MAAqB,MAAwB;AACrE,UAAM,8BAA8B,MAAM,MAAM,IAAI;AAEpD,SAAK,YAAYC,QAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AAC1C,aAAOD,QAAO,KAAK,OAAO,MAAMC,OAAM,EAAE,GAAG,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,IAClE,CAAC;AAED,SAAK,gBAAgB,EAAE,WAAW,KAAK,UAAU,CAAC;AAAA,EACpD;AAAA,EAQA,OAAO,OAAO,MAAc,MAAqB,MAA2C;AAC1F,WAAOD,QAAO,IAAI,EAAE,MAAM,OAAMC,UAAQ;AACtC,YAAM,eAAeA,MAAK,SAAS;AACnC,YAAM,WAAW,GAAG,EAAW,YAAY,CAAC;AAC5C,YAAM,aAAc,MAAM,OAAO,cAAc,YAAY;AAE3D,YAAM,YAAY,WAAW,QAAQ;AAMrC,aAAO,IAAI,UAAU,MAAMA,OAAM,IAAI;AAAA,IACvC,CAAC;AAAA,EACH;AACF;;;AIhFA,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAEpB,SAAS,mBAAmB;AACjC,SAAO,WAAW,MAAM,YAAY,EAAE,CAAC,EAAE;AAC3C;;;ACJA;AAAA,EACE;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,OAIK;AACP,OAAO,WAAW,qBAAqB;AACvC,SAAS,eAAAC,oBAAmB;AAErB,SAAS,kBAAkB,QAAyC;AACzE,QAAM,UAAU,CAAC,OAAO,OAAO,MAAM,0BAA0B;AAE/D,MAAI,OAAO,gBAAgB,MAAM;AAC/B,YAAQ,KAAK,MAAM,OAAO,eAAe,KAAK,SAAS,CAAC;AAAA,EAC1D;AAEA,MAAI,OAAO,gBAAgB,YAAY;AACrC,YAAQ,KAAK,MAAM,cAAc;AAAA,EACnC;AAEA,QAAM,WAAW,OAAO,gBAAgB,YAAY,OAAO;AAC3D,QAAM,OAAO,OAAO,gBAAgB,QAAQ;AAE5C,UAAQ,KAAK,GAAG,IAAI,IAAI,QAAQ,EAAE;AAElC,MAAI,OAAO,gBAAgB,UAAU;AACnC,YAAQ,QAAQ,WAAW,MAAM,WAAW;AAAA,EAC9C;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,QAAQ,oBAAoB,CAAC;AAAA,IACpC,aAAa;AAAA,IACb,OAAO;AAAA,IACP;AAAA,IAEA,OAAO;AAAA,MACL,aAAa,OAAO,gBAAgB;AAAA,MAEpC,gBAAgB;AAAA,QACd,SAAS,OAAO,gBAAgB;AAAA,QAChC,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBAA6B;AAC3C,QAAM,OAAOA,aAAY,EAAE;AAE3B,SAAO,QAAQ,IAAI,EAAE;AACvB;AAEO,SAAS,kBAAkB,YAAoB;AACpD,QAAM,mBAAmB,cAAc,OAAO,UAAU;AAGxD,QAAM,UAAU,iBAAiB,KAAK,CAAC,EAAE,QAAQ;AAEjD,SAAO,QAAQ,QAAQ,MAAM,GAAG,EAAE,CAAC;AACrC;AAUO,SAAS,sBACd,QACA,SACqB;AACrB,MAAI,OAAO,YAAY;AACrB,WAAOD,QAAO,OAAO,UAAU;AAAA,EACjC;AAEA,QAAM,aAAa,kBAAkB,SAAS,iBAAiB,kBAAkB;AACjF,QAAM,OAAO,WAAW,MAAM,iBAAiB;AAE/C,SAAOA,QAAO;AAAA,IACZ,MAAM;AAAA,IACN;AAAA,IACA,WAAW,KAAK;AAAA,EAClB,CAAC;AACH;","names":["server","output","n","u","n","u","output","args","output","randomBytes"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createSshTerminal
3
- } from "../chunk-M5AC7PLD.js";
3
+ } from "../chunk-ITZRY7W5.js";
4
4
 
5
5
  // src/existing-server/index.ts
6
6
  import { common } from "@highstate/library";
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "sourceHashes": {
3
- "./dist/index.js": "a230febc763ee0db43d808bc7f013b1ec5e18f681f62fd7280f6c6af51b927d1",
3
+ "./dist/index.js": "7431e121a60c2ff72e7952ca4b0e4202c67511508f7feaaffa53147d6bad33a2",
4
4
  "./dist/dns/record/index.js": "e4f4558eaa29c589553e0c99b2f12e29e55e3db434977685b4f0e033e5666ac3",
5
- "./dist/existing-server/index.js": "cc17a157185d633a0f56d9cf8c96e7e12b97c435101762b52f3ae41dc8855e12",
6
- "./dist/ssh/key-pair/index.js": "dbcfc6f2a03c439b8e87c92d2da7fd61f71233fad09222a653b38eede74638b0"
5
+ "./dist/existing-server/index.js": "179ed06984c9f8d8d3f4748105b70ec0d9417664a22bfe5af650aff75da30bf5",
6
+ "./dist/ssh/key-pair/index.js": "cfeaa0a2e69cefc625d28863c0b84bbacef14bfc15257ff196e3fe54860cc38e",
7
+ "./dist/script/index.js": "ec8cbffce012ca11ad31c6bea8959a185ea9eeb5b4e99c0c15a713331aa9c03d"
7
8
  }
8
9
  }
package/dist/index.js CHANGED
@@ -3,13 +3,19 @@ import {
3
3
  Server,
4
4
  createSshTerminal,
5
5
  generatePassword,
6
+ generatePrivateKey,
7
+ getKeysFromString,
8
+ getOrCreateSshKeyPair,
6
9
  getServerConnection
7
- } from "./chunk-M5AC7PLD.js";
10
+ } from "./chunk-ITZRY7W5.js";
8
11
  export {
9
12
  DnsRecord,
10
13
  Server,
11
14
  createSshTerminal,
12
15
  generatePassword,
16
+ generatePrivateKey,
17
+ getKeysFromString,
18
+ getOrCreateSshKeyPair,
13
19
  getServerConnection
14
20
  };
15
21
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,22 @@
1
+ import {
2
+ Server
3
+ } from "../chunk-ITZRY7W5.js";
4
+
5
+ // src/script/index.ts
6
+ import { common } from "@highstate/library";
7
+ import { forUnit } from "@highstate/pulumi";
8
+ var { name, args, inputs, outputs } = forUnit(common.script);
9
+ var server = new Server(inputs.server);
10
+ server.command({
11
+ id: name,
12
+ create: args.script,
13
+ update: args.updateScript,
14
+ delete: args.deleteScript
15
+ });
16
+ var script_default = outputs({
17
+ server: inputs.server
18
+ });
19
+ export {
20
+ script_default as default
21
+ };
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/script/index.ts"],"sourcesContent":["import { common } from \"@highstate/library\"\nimport { forUnit } from \"@highstate/pulumi\"\nimport { Server } from \"../shared\"\n\nconst { name, args, inputs, outputs } = forUnit(common.script)\n\nconst server = new Server(inputs.server)\n\nserver.command({\n id: name,\n create: args.script,\n update: args.updateScript,\n delete: args.deleteScript,\n})\n\nexport default outputs({\n server: inputs.server,\n})\n"],"mappings":";;;;;AAAA,SAAS,cAAc;AACvB,SAAS,eAAe;AAGxB,IAAM,EAAE,MAAM,MAAM,QAAQ,QAAQ,IAAI,QAAQ,OAAO,MAAM;AAE7D,IAAM,SAAS,IAAI,OAAO,OAAO,MAAM;AAEvC,OAAO,QAAQ;AAAA,EACb,IAAI;AAAA,EACJ,QAAQ,KAAK;AAAA,EACb,QAAQ,KAAK;AAAA,EACb,QAAQ,KAAK;AACf,CAAC;AAED,IAAO,iBAAQ,QAAQ;AAAA,EACrB,QAAQ,OAAO;AACjB,CAAC;","names":[]}
@@ -1,18 +1,13 @@
1
+ import {
2
+ generatePrivateKey,
3
+ getKeysFromString
4
+ } from "../../chunk-ITZRY7W5.js";
5
+
1
6
  // src/ssh/key-pair/index.ts
2
7
  import { ssh } from "@highstate/library";
3
8
  import { forUnit, getOrCreateSecret, unsecret } from "@highstate/pulumi";
4
- import { getKeys, PrivateExport } from "micro-key-producer/ssh.js";
5
- import { randomBytes } from "micro-key-producer/utils.js";
6
9
  var { secrets, outputs } = forUnit(ssh.keyPair);
7
- var privateKey = getOrCreateSecret(secrets, "privateKey", () => {
8
- const seed = randomBytes(32);
9
- return getKeys(seed).privateKey;
10
- });
11
- function getKeysFromString(privateKey2) {
12
- const privateKeyStruct = PrivateExport.decode(privateKey2);
13
- const privKey = privateKeyStruct.keys[0].privKey.privKey;
14
- return getKeys(privKey.slice(0, 32));
15
- }
10
+ var privateKey = getOrCreateSecret(secrets, "privateKey", generatePrivateKey);
16
11
  var keys = privateKey.apply(getKeysFromString);
17
12
  var key_pair_default = outputs({
18
13
  keyPair: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ssh/key-pair/index.ts"],"sourcesContent":["import { ssh } from \"@highstate/library\"\nimport { forUnit, getOrCreateSecret, unsecret } from \"@highstate/pulumi\"\nimport { getKeys, PrivateExport } from \"micro-key-producer/ssh.js\"\nimport { randomBytes } from \"micro-key-producer/utils.js\"\n\nconst { secrets, outputs } = forUnit(ssh.keyPair)\n\nconst privateKey = getOrCreateSecret(secrets, \"privateKey\", () => {\n const seed = randomBytes(32)\n\n return getKeys(seed).privateKey\n})\n\nfunction getKeysFromString(privateKey: string) {\n const privateKeyStruct = PrivateExport.decode(privateKey)\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const privKey = privateKeyStruct.keys[0].privKey.privKey as Uint8Array\n\n return getKeys(privKey.slice(0, 32))\n}\n\nconst keys = privateKey.apply(getKeysFromString)\n\nexport default outputs({\n keyPair: {\n type: \"ed25519\",\n privateKey: keys.privateKey,\n publicKey: unsecret(keys.publicKey),\n },\n $status: {\n fingerprint: {\n value: unsecret(keys.fingerprint),\n },\n publicKey: {\n value: unsecret(keys.publicKey),\n },\n },\n})\n"],"mappings":";AAAA,SAAS,WAAW;AACpB,SAAS,SAAS,mBAAmB,gBAAgB;AACrD,SAAS,SAAS,qBAAqB;AACvC,SAAS,mBAAmB;AAE5B,IAAM,EAAE,SAAS,QAAQ,IAAI,QAAQ,IAAI,OAAO;AAEhD,IAAM,aAAa,kBAAkB,SAAS,cAAc,MAAM;AAChE,QAAM,OAAO,YAAY,EAAE;AAE3B,SAAO,QAAQ,IAAI,EAAE;AACvB,CAAC;AAED,SAAS,kBAAkBA,aAAoB;AAC7C,QAAM,mBAAmB,cAAc,OAAOA,WAAU;AAGxD,QAAM,UAAU,iBAAiB,KAAK,CAAC,EAAE,QAAQ;AAEjD,SAAO,QAAQ,QAAQ,MAAM,GAAG,EAAE,CAAC;AACrC;AAEA,IAAM,OAAO,WAAW,MAAM,iBAAiB;AAE/C,IAAO,mBAAQ,QAAQ;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,IACN,YAAY,KAAK;AAAA,IACjB,WAAW,SAAS,KAAK,SAAS;AAAA,EACpC;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,MACX,OAAO,SAAS,KAAK,WAAW;AAAA,IAClC;AAAA,IACA,WAAW;AAAA,MACT,OAAO,SAAS,KAAK,SAAS;AAAA,IAChC;AAAA,EACF;AACF,CAAC;","names":["privateKey"]}
1
+ {"version":3,"sources":["../../../src/ssh/key-pair/index.ts"],"sourcesContent":["import { ssh } from \"@highstate/library\"\nimport { forUnit, getOrCreateSecret, unsecret } from \"@highstate/pulumi\"\nimport { generatePrivateKey, getKeysFromString } from \"../../shared\"\n\nconst { secrets, outputs } = forUnit(ssh.keyPair)\n\nconst privateKey = getOrCreateSecret(secrets, \"privateKey\", generatePrivateKey)\nconst keys = privateKey.apply(getKeysFromString)\n\nexport default outputs({\n keyPair: {\n type: \"ed25519\",\n privateKey: keys.privateKey,\n publicKey: unsecret(keys.publicKey),\n },\n $status: {\n fingerprint: {\n value: unsecret(keys.fingerprint),\n },\n publicKey: {\n value: unsecret(keys.publicKey),\n },\n },\n})\n"],"mappings":";;;;;;AAAA,SAAS,WAAW;AACpB,SAAS,SAAS,mBAAmB,gBAAgB;AAGrD,IAAM,EAAE,SAAS,QAAQ,IAAI,QAAQ,IAAI,OAAO;AAEhD,IAAM,aAAa,kBAAkB,SAAS,cAAc,kBAAkB;AAC9E,IAAM,OAAO,WAAW,MAAM,iBAAiB;AAE/C,IAAO,mBAAQ,QAAQ;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,IACN,YAAY,KAAK;AAAA,IACjB,WAAW,SAAS,KAAK,SAAS;AAAA,EACpC;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,MACX,OAAO,SAAS,KAAK,WAAW;AAAA,IAClC;AAAA,IACA,WAAW;AAAA,MACT,OAAO,SAAS,KAAK,SAAS;AAAA,IAChC;AAAA,EACF;AACF,CAAC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highstate/common",
3
- "version": "0.7.8",
3
+ "version": "0.7.10",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -13,7 +13,8 @@
13
13
  },
14
14
  "./dns/record": "./dist/dns/record/index.js",
15
15
  "./existing-server": "./dist/existing-server/index.js",
16
- "./ssh/key-pair": "./dist/ssh/key-pair/index.js"
16
+ "./ssh/key-pair": "./dist/ssh/key-pair/index.js",
17
+ "./script": "./dist/script/index.js"
17
18
  },
18
19
  "publishConfig": {
19
20
  "access": "public"
@@ -22,7 +23,7 @@
22
23
  "build": "highstate build"
23
24
  },
24
25
  "dependencies": {
25
- "@highstate/pulumi": "^0.7.8",
26
+ "@highstate/pulumi": "^0.7.10",
26
27
  "@noble/hashes": "^1.7.1",
27
28
  "@pulumi/command": "^1.0.2",
28
29
  "micro-key-producer": "^0.7.3"
@@ -31,7 +32,7 @@
31
32
  "@highstate/library": "workspace:^0.4.4"
32
33
  },
33
34
  "devDependencies": {
34
- "@highstate/cli": "^0.7.8"
35
+ "@highstate/cli": "^0.7.10"
35
36
  },
36
- "gitHead": "c74d82b9eb6e6dc0103a51fb0c840ee3ca295a67"
37
+ "gitHead": "171465dab44ebcedd1d1eb9e5369fb1c88daa480"
37
38
  }
@@ -0,0 +1,18 @@
1
+ import { common } from "@highstate/library"
2
+ import { forUnit } from "@highstate/pulumi"
3
+ import { Server } from "../shared"
4
+
5
+ const { name, args, inputs, outputs } = forUnit(common.script)
6
+
7
+ const server = new Server(inputs.server)
8
+
9
+ server.command({
10
+ id: name,
11
+ create: args.script,
12
+ update: args.updateScript,
13
+ delete: args.deleteScript,
14
+ })
15
+
16
+ export default outputs({
17
+ server: inputs.server,
18
+ })
package/src/shared/ssh.ts CHANGED
@@ -1,5 +1,14 @@
1
- import type { common } from "@highstate/library"
2
- import { getUnitInstanceName, type InstanceTerminal } from "@highstate/pulumi"
1
+ import type { common, ssh } from "@highstate/library"
2
+ import {
3
+ getOrCreateSecret,
4
+ getUnitInstanceName,
5
+ output,
6
+ Output,
7
+ type Input,
8
+ type InstanceTerminal,
9
+ } from "@highstate/pulumi"
10
+ import getKeys, { PrivateExport } from "micro-key-producer/ssh.js"
11
+ import { randomBytes } from "micro-key-producer/utils.js"
3
12
 
4
13
  export function createSshTerminal(server: common.Server): InstanceTerminal {
5
14
  const command = ["ssh", "-tt", "-o", "StrictHostKeyChecking=no"]
@@ -38,3 +47,44 @@ export function createSshTerminal(server: common.Server): InstanceTerminal {
38
47
  },
39
48
  }
40
49
  }
50
+
51
+ export function generatePrivateKey(): string {
52
+ const seed = randomBytes(32)
53
+
54
+ return getKeys(seed).privateKey
55
+ }
56
+
57
+ export function getKeysFromString(privateKey: string) {
58
+ const privateKeyStruct = PrivateExport.decode(privateKey)
59
+
60
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
61
+ const privKey = privateKeyStruct.keys[0].privKey.privKey as Uint8Array
62
+
63
+ return getKeys(privKey.slice(0, 32))
64
+ }
65
+
66
+ export type SshKeyPairInputs = {
67
+ sshKeyPair?: Input<ssh.KeyPair>
68
+ }
69
+
70
+ export type SshKeyPairSecrets = {
71
+ sshPrivateKey?: Input<string>
72
+ }
73
+
74
+ export function getOrCreateSshKeyPair(
75
+ inputs: SshKeyPairInputs,
76
+ secrets: Output<SshKeyPairSecrets>,
77
+ ): Output<ssh.KeyPair> {
78
+ if (inputs.sshKeyPair) {
79
+ return output(inputs.sshKeyPair)
80
+ }
81
+
82
+ const privateKey = getOrCreateSecret(secrets, "sshPrivateKey", generatePrivateKey)
83
+ const keys = privateKey.apply(getKeysFromString)
84
+
85
+ return output({
86
+ type: "ed25519",
87
+ privateKey,
88
+ publicKey: keys.publicKey,
89
+ })
90
+ }
@@ -1,25 +1,10 @@
1
1
  import { ssh } from "@highstate/library"
2
2
  import { forUnit, getOrCreateSecret, unsecret } from "@highstate/pulumi"
3
- import { getKeys, PrivateExport } from "micro-key-producer/ssh.js"
4
- import { randomBytes } from "micro-key-producer/utils.js"
3
+ import { generatePrivateKey, getKeysFromString } from "../../shared"
5
4
 
6
5
  const { secrets, outputs } = forUnit(ssh.keyPair)
7
6
 
8
- const privateKey = getOrCreateSecret(secrets, "privateKey", () => {
9
- const seed = randomBytes(32)
10
-
11
- return getKeys(seed).privateKey
12
- })
13
-
14
- function getKeysFromString(privateKey: string) {
15
- const privateKeyStruct = PrivateExport.decode(privateKey)
16
-
17
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
18
- const privKey = privateKeyStruct.keys[0].privKey.privKey as Uint8Array
19
-
20
- return getKeys(privKey.slice(0, 32))
21
- }
22
-
7
+ const privateKey = getOrCreateSecret(secrets, "privateKey", generatePrivateKey)
23
8
  const keys = privateKey.apply(getKeysFromString)
24
9
 
25
10
  export default outputs({
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/server.ts","../src/shared/dns.ts","../../../node_modules/remeda/dist/chunk-D6FCK2GA.js","../../../node_modules/remeda/dist/chunk-WIMGWYZL.js","../../../node_modules/remeda/dist/chunk-VG2NVNXT.js","../src/shared/passwords.ts","../src/shared/ssh.ts"],"sourcesContent":["import { remote, type types } from \"@pulumi/command\"\nimport { output, Resource, type Input, type InputOrArray, type Output } from \"@highstate/pulumi\"\nimport { common } from \"@highstate/library\"\n\nexport function getServerConnection(\n server: Input<common.Server>,\n): Output<types.input.remote.ConnectionArgs> {\n return output(server).apply(server => ({\n host: server.endpoint,\n port: server.sshCredentials?.port ?? 22,\n user: server.sshCredentials?.user ?? \"root\",\n password: server.sshCredentials?.password,\n privateKey: server.sshCredentials?.privateKey,\n dialErrorLimit: 3,\n }))\n}\n\nexport interface CommandOptions {\n id: string\n create: Input<string>\n update?: Input<string>\n delete?: Input<string>\n dependsOn?: InputOrArray<Resource>\n}\n\nexport class Server {\n public readonly server: Output<common.Server>\n public readonly connection: Output<types.input.remote.ConnectionArgs>\n\n public get endpoint(): Output<string> {\n return this.server.endpoint\n }\n\n public get hostname(): Output<string> {\n return this.server.hostname\n }\n\n constructor(server: Input<common.Server>) {\n this.server = output(server)\n this.connection = getServerConnection(this.server)\n }\n\n public command(options: CommandOptions): remote.Command {\n return new remote.Command(\n options.id,\n {\n connection: this.connection,\n create: options.create,\n update: options.update,\n delete: options.delete,\n },\n { dependsOn: options.dependsOn },\n )\n }\n}\n","import type { dns } from \"@highstate/library\"\nimport {\n ComponentResource,\n output,\n Output,\n Resource,\n type Input,\n type ResourceOptions,\n type Unwrap,\n} from \"@highstate/pulumi\"\nimport { capitalize } from \"remeda\"\n\nexport type DnsRecordArgs = {\n /**\n * The DNS provider to use.\n */\n provider: Input<dns.Provider>\n\n /**\n * The name of the DNS record.\n * If not provided, the name of the resource will be used.\n */\n name?: Input<string>\n\n /**\n * The type of the DNS record.\n */\n type: Input<string>\n\n /**\n * The value of the DNS record.\n */\n value: Input<string>\n\n /**\n * Whether the DNS record is proxied (e.g. to provide DDoS protection).\n *\n * Available only for public IPs and some DNS providers like Cloudflare.\n * If not supported, the DNS provider will ignore this value.\n */\n proxied?: Input<boolean>\n}\n\nexport abstract class DnsRecord extends ComponentResource {\n /**\n * The underlying dns record resource.\n */\n public readonly dnsRecord: Output<Resource>\n\n constructor(name: string, args: DnsRecordArgs, opts?: ResourceOptions) {\n super(\"highstate:common:DnsRecord\", name, args, opts)\n\n this.dnsRecord = output(args).apply(args => {\n return output(this.create(name, args, { ...opts, parent: this }))\n })\n\n this.registerOutputs({ dnsRecord: this.dnsRecord })\n }\n\n protected abstract create(\n name: string,\n args: Unwrap<DnsRecordArgs>,\n opts?: ResourceOptions,\n ): Input<Resource>\n\n static create(name: string, args: DnsRecordArgs, opts?: ResourceOptions): Output<DnsRecord> {\n return output(args).apply(async args => {\n const providerType = args.provider.type\n const implName = `${capitalize(providerType)}DnsRecord`\n const implModule = (await import(`@highstate/${providerType}`)) as Record<string, unknown>\n\n const implClass = implModule[implName] as new (\n name: string,\n args: Unwrap<DnsRecordArgs>,\n opts?: ResourceOptions,\n ) => DnsRecord\n\n return new implClass(name, args, opts)\n })\n }\n}\n","function u(o,n,a){let t=r=>o(r,...n);return a===void 0?t:Object.assign(t,{lazy:a,lazyArgs:n})}export{u as a};\n","import{a as t}from\"./chunk-D6FCK2GA.js\";function u(r,n,o){let a=r.length-n.length;if(a===0)return r(...n);if(a===1)return t(r,n,o);throw new Error(\"Wrong number of arguments\")}export{u as a};\n","import{a as i}from\"./chunk-WIMGWYZL.js\";function n(...t){return i(e,t)}var e=t=>`${t[0]?.toUpperCase()??\"\"}${t.slice(1)}`;export{n as a};\n","import { randomBytes } from \"@noble/hashes/utils\"\nimport { secureMask } from \"micro-key-producer/password.js\"\n\nexport function generatePassword() {\n return secureMask.apply(randomBytes(32)).password\n}\n","import type { common } from \"@highstate/library\"\nimport { getUnitInstanceName, type InstanceTerminal } from \"@highstate/pulumi\"\n\nexport function createSshTerminal(server: common.Server): InstanceTerminal {\n const command = [\"ssh\", \"-tt\", \"-o\", \"StrictHostKeyChecking=no\"]\n\n if (server.sshCredentials?.port) {\n command.push(\"-p\", server.sshCredentials.port.toString())\n }\n\n if (server.sshCredentials?.privateKey) {\n command.push(\"-i\", \"/private-key\")\n }\n\n const endpoint = server.sshCredentials?.endpoint ?? server.endpoint\n const user = server.sshCredentials?.user ?? \"root\"\n\n command.push(`${user}@${endpoint}`)\n\n if (server.sshCredentials?.password) {\n command.unshift(\"sshpass\", \"-f\", \"/password\")\n }\n\n return {\n name: \"ssh\",\n title: `SSH: ${getUnitInstanceName()}`,\n description: \"Connect to the server via SSH\",\n image: \"ghcr.io/exeteres/highstate/terminal-ssh\",\n command,\n\n files: {\n \"/password\": server.sshCredentials?.password,\n\n \"/private-key\": {\n content: server.sshCredentials?.privateKey,\n mode: 0o600,\n },\n },\n }\n}\n"],"mappings":"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","names":["server","output","n","u","n","u","output","args"]}