Compare commits
4 Commits
jill/migra
...
jill/handl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd693ea721 | ||
|
|
75acf919f3 | ||
|
|
c4aeeff620 | ||
|
|
e7517d7b3e |
46
.github/workflows/e2e-tests.yml
vendored
46
.github/workflows/e2e-tests.yml
vendored
@@ -66,6 +66,8 @@ jobs:
|
||||
echo "SECRET_WITH_FILE=op://${{ secrets.VAULT }}/file-secret/test.txt" >> tests/.env.tpl
|
||||
echo "SECRET_WITH_FILE_IN_SECTION=op://${{ secrets.VAULT }}/file-secret/file section/test.txt" >> tests/.env.tpl
|
||||
echo "DOUBLE_SECTION_SECRET=op://${{ secrets.VAULT }}/double-section-secret/test-section/password" >> tests/.env.tpl
|
||||
echo "SSH_PRIVATE_KEY=op://${{ secrets.VAULT }}/test-ssh-key/private key" >> tests/.env.tpl
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH=op://${{ secrets.VAULT }}/test-ssh-key/private key?ssh-format=openssh" >> tests/.env.tpl
|
||||
|
||||
- name: Generate .vaultId_env.tpl
|
||||
shell: bash
|
||||
@@ -76,6 +78,8 @@ jobs:
|
||||
echo "SECRET_WITH_FILE=op://${{ secrets.VAULT_ID }}/file-secret/test.txt" >> tests/.vaultId_env.tpl
|
||||
echo "SECRET_WITH_FILE_IN_SECTION=op://${{ secrets.VAULT_ID }}/file-secret/file section/test.txt" >> tests/.vaultId_env.tpl
|
||||
echo "DOUBLE_SECTION_SECRET=op://${{ secrets.VAULT_ID }}/double-section-secret/test-section/password" >> tests/.vaultId_env.tpl
|
||||
echo "SSH_PRIVATE_KEY=op://${{ secrets.VAULT_ID }}/test-ssh-key/private key" >> tests/.vaultId_env.tpl
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH=op://${{ secrets.VAULT_ID }}/test-ssh-key/private key?ssh-format=openssh" >> tests/.vaultId_env.tpl
|
||||
|
||||
- name: Configure Service account
|
||||
uses: ./configure
|
||||
@@ -95,6 +99,8 @@ jobs:
|
||||
SECRET_WITH_FILE: op://${{ secrets.VAULT }}/file-secret/test.txt
|
||||
SECRET_WITH_FILE_IN_SECTION: op://${{ secrets.VAULT }}/file-secret/file section/test.txt
|
||||
DOUBLE_SECTION_SECRET: op://${{ secrets.VAULT }}/double-section-secret/test-section/password
|
||||
SSH_PRIVATE_KEY: op://${{ secrets.VAULT }}/test-ssh-key/private key
|
||||
SSH_PRIVATE_KEY_OPENSSH: op://${{ secrets.VAULT }}/test-ssh-key/private key?ssh-format=openssh
|
||||
OP_ENV_FILE: ./tests/.env.tpl
|
||||
|
||||
- name: Assert test secret values [step output]
|
||||
@@ -110,6 +116,8 @@ jobs:
|
||||
SECRET_WITH_FILE: ${{ steps.load_secrets.outputs.SECRET_WITH_FILE }}
|
||||
SECRET_WITH_FILE_IN_SECTION: ${{ steps.load_secrets.outputs.SECRET_WITH_FILE_IN_SECTION }}
|
||||
DOUBLE_SECTION_SECRET: ${{ steps.load_secrets.outputs.DOUBLE_SECTION_SECRET }}
|
||||
SSH_PRIVATE_KEY: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY }}
|
||||
SSH_PRIVATE_KEY_OPENSSH: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY_OPENSSH }}
|
||||
run: ./tests/assert-env-set.sh
|
||||
|
||||
- name: Assert test secret values [exported env]
|
||||
@@ -117,6 +125,19 @@ jobs:
|
||||
shell: bash
|
||||
run: ./tests/assert-env-set.sh
|
||||
|
||||
- name: Assert SSH keys [step output]
|
||||
if: ${{ !matrix.export-env }}
|
||||
shell: bash
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY }}
|
||||
SSH_PRIVATE_KEY_OPENSSH: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY_OPENSSH }}
|
||||
run: ./tests/assert-ssh-keys.sh
|
||||
|
||||
- name: Assert SSH keys [exported env]
|
||||
if: ${{ matrix.export-env }}
|
||||
shell: bash
|
||||
run: ./tests/assert-ssh-keys.sh
|
||||
|
||||
- name: Remove secrets [exported env]
|
||||
if: ${{ matrix.export-env }}
|
||||
uses: ./
|
||||
@@ -156,6 +177,8 @@ jobs:
|
||||
SECRET_WITH_FILE: op://${{ secrets.VAULT_ID }}/file-secret/test.txt
|
||||
SECRET_WITH_FILE_IN_SECTION: op://${{ secrets.VAULT_ID }}/file-secret/file section/test.txt
|
||||
DOUBLE_SECTION_SECRET: op://${{ secrets.VAULT_ID }}/double-section-secret/test-section/password
|
||||
SSH_PRIVATE_KEY: op://${{ secrets.VAULT_ID }}/test-ssh-key/private key
|
||||
SSH_PRIVATE_KEY_OPENSSH: op://${{ secrets.VAULT_ID }}/test-ssh-key/private key?ssh-format=openssh
|
||||
OP_ENV_FILE: ./tests/.vaultId_env.tpl
|
||||
|
||||
- name: Assert test secret values [vault by ID]
|
||||
@@ -171,6 +194,8 @@ jobs:
|
||||
SECRET_WITH_FILE: ${{ steps.load_secrets_by_vault_id.outputs.SECRET_WITH_FILE }}
|
||||
SECRET_WITH_FILE_IN_SECTION: ${{ steps.load_secrets_by_vault_id.outputs.SECRET_WITH_FILE_IN_SECTION }}
|
||||
DOUBLE_SECTION_SECRET: ${{ steps.load_secrets_by_vault_id.outputs.DOUBLE_SECTION_SECRET }}
|
||||
SSH_PRIVATE_KEY: ${{ steps.load_secrets_by_vault_id.outputs.SSH_PRIVATE_KEY }}
|
||||
SSH_PRIVATE_KEY_OPENSSH: ${{ steps.load_secrets_by_vault_id.outputs.SSH_PRIVATE_KEY_OPENSSH }}
|
||||
run: ./tests/assert-env-set.sh
|
||||
|
||||
test-connect:
|
||||
@@ -210,6 +235,8 @@ jobs:
|
||||
echo "SECRET_WITH_FILE=op://${{ secrets.VAULT }}/file-secret/test.txt" >> tests/.env.tpl
|
||||
echo "SECRET_WITH_FILE_IN_SECTION=op://${{ secrets.VAULT }}/file-secret/file section/test.txt" >> tests/.env.tpl
|
||||
echo "DOUBLE_SECTION_SECRET=op://${{ secrets.VAULT }}/double-section-secret/test-section/password" >> tests/.env.tpl
|
||||
echo "SSH_PRIVATE_KEY=op://${{ secrets.VAULT }}/test-ssh-key/private key" >> tests/.env.tpl
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH=op://${{ secrets.VAULT }}/test-ssh-key/private key?ssh-format=openssh" >> tests/.env.tpl
|
||||
|
||||
- name: Generate .vaultId_env.tpl
|
||||
run: |
|
||||
@@ -219,6 +246,8 @@ jobs:
|
||||
echo "SECRET_WITH_FILE=op://${{ secrets.VAULT_ID }}/file-secret/test.txt" >> tests/.vaultId_env.tpl
|
||||
echo "SECRET_WITH_FILE_IN_SECTION=op://${{ secrets.VAULT_ID }}/file-secret/file section/test.txt" >> tests/.vaultId_env.tpl
|
||||
echo "DOUBLE_SECTION_SECRET=op://${{ secrets.VAULT_ID }}/double-section-secret/test-section/password" >> tests/.vaultId_env.tpl
|
||||
echo "SSH_PRIVATE_KEY=op://${{ secrets.VAULT_ID }}/test-ssh-key/private key" >> tests/.vaultId_env.tpl
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH=op://${{ secrets.VAULT_ID }}/test-ssh-key/private key?ssh-format=openssh" >> tests/.vaultId_env.tpl
|
||||
|
||||
- name: Launch 1Password Connect instance
|
||||
env:
|
||||
@@ -246,6 +275,8 @@ jobs:
|
||||
SECRET_WITH_FILE: op://${{ secrets.VAULT }}/file-secret/test.txt
|
||||
SECRET_WITH_FILE_IN_SECTION: op://${{ secrets.VAULT }}/file-secret/file section/test.txt
|
||||
DOUBLE_SECTION_SECRET: op://${{ secrets.VAULT }}/double-section-secret/test-section/password
|
||||
SSH_PRIVATE_KEY: op://${{ secrets.VAULT }}/test-ssh-key/private key
|
||||
SSH_PRIVATE_KEY_OPENSSH: op://${{ secrets.VAULT }}/test-ssh-key/private key?ssh-format=openssh
|
||||
OP_ENV_FILE: ./tests/.env.tpl
|
||||
|
||||
- name: Assert test secret values [step output]
|
||||
@@ -260,12 +291,27 @@ jobs:
|
||||
SECRET_WITH_FILE: ${{ steps.load_secrets.outputs.SECRET_WITH_FILE }}
|
||||
SECRET_WITH_FILE_IN_SECTION: ${{ steps.load_secrets.outputs.SECRET_WITH_FILE_IN_SECTION }}
|
||||
DOUBLE_SECTION_SECRET: ${{ steps.load_secrets.outputs.DOUBLE_SECTION_SECRET }}
|
||||
SSH_PRIVATE_KEY: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY }}
|
||||
SSH_PRIVATE_KEY_OPENSSH: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY_OPENSSH }}
|
||||
run: ./tests/assert-env-set.sh
|
||||
|
||||
- name: Assert test secret values [exported env]
|
||||
if: ${{ matrix.export-env }}
|
||||
run: ./tests/assert-env-set.sh
|
||||
|
||||
- name: Assert SSH keys [step output]
|
||||
if: ${{ !matrix.export-env }}
|
||||
shell: bash
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY }}
|
||||
SSH_PRIVATE_KEY_OPENSSH: ${{ steps.load_secrets.outputs.SSH_PRIVATE_KEY_OPENSSH }}
|
||||
run: ./tests/assert-ssh-keys.sh
|
||||
|
||||
- name: Assert SSH keys [exported env]
|
||||
if: ${{ matrix.export-env }}
|
||||
shell: bash
|
||||
run: ./tests/assert-ssh-keys.sh
|
||||
|
||||
- name: Remove secrets [exported env]
|
||||
if: ${{ matrix.export-env }}
|
||||
uses: ./
|
||||
|
||||
114
package-lock.json
generated
114
package-lock.json
generated
@@ -15,13 +15,15 @@
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/tool-cache": "^2.0.2",
|
||||
"dotenv": "^17.2.2"
|
||||
"dotenv": "^17.2.2",
|
||||
"sshpk": "^1.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@1password/eslint-config": "^4.3.1",
|
||||
"@1password/prettier-config": "^1.2.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.30",
|
||||
"@types/sshpk": "^1.17.4",
|
||||
"@vercel/ncc": "^0.38.1",
|
||||
"husky": "^9.0.11",
|
||||
"jest": "^29.7.0",
|
||||
@@ -1302,6 +1304,15 @@
|
||||
"@sinonjs/commons": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-V91DSJ2l0h0gRhVP4oBfBzRBN9lAbPUkGDMCnwedqPKX2d84aAMc9CulOvxdw1f7DfEYx99afab+Rsm3e52jhA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||
@@ -1426,6 +1437,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/sshpk": {
|
||||
"version": "1.17.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/sshpk/-/sshpk-1.17.4.tgz",
|
||||
"integrity": "sha512-5gI/7eJn6wmkuIuFY8JZJ1g5b30H9K5U5vKrvOuYu+hoZLb2xcVEgxhYZ2Vhbs0w/ACyzyfkJq0hQtBfSCugjw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/asn1": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
||||
@@ -1980,6 +2001,22 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-types-flow": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
|
||||
@@ -2180,6 +2217,14 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"dependencies": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
@@ -2637,6 +2682,17 @@
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
|
||||
@@ -2859,6 +2915,15 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
|
||||
"dependencies": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
@@ -4092,6 +4157,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
@@ -5644,6 +5717,11 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
|
||||
},
|
||||
"node_modules/jsdoc-type-pratt-parser": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
|
||||
@@ -7145,6 +7223,11 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
@@ -7406,6 +7489,30 @@
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/sshpk": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
|
||||
"integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
|
||||
"dependencies": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
},
|
||||
"bin": {
|
||||
"sshpk-conv": "bin/sshpk-conv",
|
||||
"sshpk-sign": "bin/sshpk-sign",
|
||||
"sshpk-verify": "bin/sshpk-verify"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stack-utils": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||
@@ -7874,6 +7981,11 @@
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
||||
@@ -46,13 +46,15 @@
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/tool-cache": "^2.0.2",
|
||||
"dotenv": "^17.2.2"
|
||||
"dotenv": "^17.2.2",
|
||||
"sshpk": "^1.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@1password/eslint-config": "^4.3.1",
|
||||
"@1password/prettier-config": "^1.2.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.30",
|
||||
"@types/sshpk": "^1.17.4",
|
||||
"@vercel/ncc": "^0.38.1",
|
||||
"husky": "^9.0.11",
|
||||
"jest": "^29.7.0",
|
||||
|
||||
30
src/utils.ts
30
src/utils.ts
@@ -1,4 +1,5 @@
|
||||
import * as core from "@actions/core";
|
||||
import sshpk from "sshpk";
|
||||
import { read } from "@1password/op-js";
|
||||
import { createClient, Secrets } from "@1password/sdk";
|
||||
import { OnePasswordConnect, FullItem, OPConnect } from "@1password/connect";
|
||||
@@ -17,6 +18,8 @@ interface ParsedOpRef {
|
||||
item: string;
|
||||
section: string | undefined;
|
||||
field: string;
|
||||
|
||||
queryParams: string | undefined;
|
||||
}
|
||||
|
||||
export const parseOpRef = (ref: string): ParsedOpRef => {
|
||||
@@ -47,11 +50,14 @@ export const parseOpRef = (ref: string): ParsedOpRef => {
|
||||
throw new Error(`Invalid op reference: item is required`);
|
||||
}
|
||||
|
||||
// Last segment is always the field
|
||||
const field = segments[segments.length - 1] ?? "";
|
||||
// Last segment is the field; it may include a query string (e.g. "private key?ssh-format=openssh")
|
||||
const lastSegment = segments[segments.length - 1] ?? "";
|
||||
const [fieldPart, queryPart] = lastSegment.split("?");
|
||||
const field = fieldPart ?? "";
|
||||
if (!field) {
|
||||
throw new Error(`Invalid op reference: field is required`);
|
||||
}
|
||||
const queryParams = queryPart ?? undefined;
|
||||
|
||||
// Second to last segment is the section if it exists
|
||||
let section: string | undefined;
|
||||
@@ -69,6 +75,7 @@ export const parseOpRef = (ref: string): ParsedOpRef => {
|
||||
item,
|
||||
field,
|
||||
section,
|
||||
queryParams,
|
||||
};
|
||||
};
|
||||
// #endregion
|
||||
@@ -269,6 +276,19 @@ const createConnectClient = (host: string, token: string): OPConnect => {
|
||||
throw new Error(`Connect authentication failed: ${message}`);
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const toOpenSSH = (value: string, _queryParams: string | undefined): string => {
|
||||
try {
|
||||
const key = sshpk.parsePrivateKey(value, "auto");
|
||||
return key.toString("openssh");
|
||||
} catch {
|
||||
core.warning(
|
||||
`Failed to parse private key to OpenSSH, returning original value`,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
// #endregion
|
||||
|
||||
// #region Shared helpers and auth
|
||||
@@ -434,7 +454,11 @@ const loadSecretsViaConnect = async (
|
||||
|
||||
// Get the secret value from the item as Connect returns a full item object
|
||||
const secretValue = await getSecretFromConnectItem(client, item, parsed);
|
||||
setResolvedSecret(envName, secretValue, shouldExportEnv);
|
||||
let valueToSet = secretValue;
|
||||
if (parsed.queryParams?.includes("ssh-format=openssh")) {
|
||||
valueToSet = toOpenSSH(secretValue, parsed.queryParams);
|
||||
}
|
||||
setResolvedSecret(envName, valueToSet, shouldExportEnv);
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
throw new Error(`Failed to load ref "${ref}": ${msg}`);
|
||||
|
||||
@@ -21,3 +21,6 @@ assert_env_unset "FILE_MULTILINE_SECRET"
|
||||
assert_env_unset "SECRET_WITH_FILE"
|
||||
assert_env_unset "SECRET_WITH_FILE_IN_SECTION"
|
||||
assert_env_unset "DOUBLE_SECTION_SECRET"
|
||||
|
||||
assert_env_unset "SSH_PRIVATE_KEY"
|
||||
assert_env_unset "SSH_PRIVATE_KEY_OPENSSH"
|
||||
|
||||
34
tests/assert-ssh-keys.sh
Executable file
34
tests/assert-ssh-keys.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# SSH_PRIVATE_KEY: any private key format
|
||||
v="$(printenv SSH_PRIVATE_KEY)"
|
||||
if [ -z "$v" ]; then
|
||||
echo "SSH_PRIVATE_KEY is not set"
|
||||
exit 1
|
||||
fi
|
||||
if ! echo "$v" | head -1 | grep -qE -- '^-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----'; then
|
||||
echo "SSH_PRIVATE_KEY does not start with a private key header"
|
||||
exit 1
|
||||
fi
|
||||
if ! echo "$v" | tail -1 | grep -qE -- '-----END (RSA |EC |OPENSSH )?PRIVATE KEY-----$'; then
|
||||
echo "SSH_PRIVATE_KEY does not end with a private key footer"
|
||||
exit 1
|
||||
fi
|
||||
echo "SSH_PRIVATE_KEY has valid key format"
|
||||
|
||||
# SSH_PRIVATE_KEY_OPENSSH: OpenSSH format only
|
||||
v="$(printenv SSH_PRIVATE_KEY_OPENSSH)"
|
||||
if [ -z "$v" ]; then
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH is not set"
|
||||
exit 1
|
||||
fi
|
||||
if ! echo "$v" | head -1 | grep -q -- '-----BEGIN OPENSSH PRIVATE KEY-----'; then
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH is not in OpenSSH format"
|
||||
exit 1
|
||||
fi
|
||||
if ! echo "$v" | tail -1 | grep -q -- '-----END OPENSSH PRIVATE KEY-----$'; then
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH does not end with OpenSSH private key footer"
|
||||
exit 1
|
||||
fi
|
||||
echo "SSH_PRIVATE_KEY_OPENSSH has valid OpenSSH key format"
|
||||
Reference in New Issue
Block a user