Skip to content

Commit

Permalink
Configure PUBKEY_SSH_FIRST_USER
Browse files Browse the repository at this point in the history
  • Loading branch information
usimd committed May 14, 2024
1 parent 6f631e5 commit 63ceb92
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 10 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ env:
CONFIG_LOCALE: de_DE.UTF-8
CONFIG_USERNAME: pi-gen
CONFIG_HOSTNAME: pi-gen-test
CONFIG_PUBLIC_KEY: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAoK4bf7Tj47S67Mf3aCsRPOcYU2F91xLBJ4U4n9jqgsAf75NWFX5UfoRQhWsGVsCYfA84ZTYIrIHMw57CLA2gM= [email protected]

jobs:

Expand Down Expand Up @@ -57,6 +58,7 @@ jobs:
wpa-essid: foo
wpa-password: '1234567890'
timezone: ${{ env.CONFIG_TIMEZONE }}
pubkey-ssh-first-user: ${{ env.CONFIG_PUBLIC_KEY }}

- name: List working directory
run: tree
Expand All @@ -77,6 +79,7 @@ jobs:
source ${ROOTFS_DIR}/etc/default/locale
test "$LANG" = "$CONFIG_LOCALE"
test "$(cat ${ROOTFS_DIR}/etc/timezone)" = "$CONFIG_TIMEZONE"
test "$(sudo cat ${ROOTFS_DIR}/home/${CONFIG_USERNAME}/.ssh/authorized_keys)" = "$CONFIG_PUBLIC_KEY"
- name: Remove test label from PR (if set)
uses: actions-ecosystem/action-remove-labels@v1
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ tries to make sure the stage is respected and its changes are included in the fi
# the pi-gen repository.
pi-gen-version: arm64

# Setting to `1` will disable password authentication for SSH and enable public
# key authentication. Note that if SSH is not enabled this will take effect when
# SSH becomes enabled.
pubkey-only-ssh: 0

# Setting this to a value will make that value the contents of the
# FIRST_USER_NAME's ~/.ssh/authorized_keys. Obviously the value should therefore
# be a valid authorized_keys file. Note that this does not automatically enable
# SSH.
pubkey-ssh-first-user: ''

# The release version to build images against. Valid values are jessie, stretch,
# buster, bullseye, bookworm, and testing.
release: bookworm
Expand Down
26 changes: 26 additions & 0 deletions __test__/pi-gen-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ describe('PiGenConfig', () => {
'exportLastStageOnly',
'no',
'export-last-stage-only must be either set to "true" or "false", was: no'
],
[
'enableSsh',
'yes',
'enable-ssh must be set to either "0" or "1" but was: yes'
],
[
'pubkeyOnlySsh',
'yes',
'pubkey-only-ssh must be set to either "0" or "1" but was: yes'
],
[
'pubkeySshFirstUser',
'ssh-foo vnqf493rn34xzrm234yru13ß48rnz1x034ztn== [email protected]',
'pubkey-ssh-first-user does not seem to be a valid list of public key according to "ssh-keygen -l", here\'s its output'
]
])(
'rejects %s with invalid value %s',
Expand Down Expand Up @@ -161,4 +176,15 @@ describe('PiGenConfig', () => {
)
}
})

it('should accept valid public key file', async () => {
const piGenConfig = {
...DEFAULT_CONFIG,
stageList: ['stage0', 'stage1', 'stage2'],
pubkeySshFirstUser: `ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF71eRtNA2CqGiKYQLI6ozVyW1XKJUXOqkH1r3ZWIruDvckuwxBUZYMvB5si4PkteJqKJnFsO74LesgxTvacxNELgHvxXCJ4XmuT0O7XujwrFCO6dARYyf+RUO5XKt0LegmbqMq3faE7SMmVJnl39quLWojGZ8kUUeS6rg089l7X9LxBA== [email protected]
ssh-dss AAAAB3NzaC1kc3MAAAEBAI95Ndm5qum/q+2Ies9JUbbzLsWeO683GOjqxJYfPv02BudDUanEGDM5uAnnwq4cU5unR1uF0BGtuLR5h3VJhGlcrA6PFLM2CCiiL/onEQo9YqmTRTQJoP5pbEZY+EvdIIGcNwmgEFexla3NACM9ulSEtikfnWSO+INEhneXnOwEtDSmrC516Zhd4j2wKS/BEYyf+p2BgeczjbeStzDXueNJWS9oCZhyFTkV6j1ri0ZTxjNFj4A7MqTC4PJykCVuTj+KOwg4ocRQ5OGMGimjfd9eoUPeS2b/BJA+1c8WI+FY1IfGCOl/IRzYHcojy244B2X4IuNCvkhMBXY5OWAc1mcAAAAdALr2lqaFePff3uf6Z8l3x4XvMrIzuuWAwLzVaV0AAAEAFqZcWCBIUHBOdQKjl1cEDTTaOjR4wVTU5KXALSQu4E+W5h5L0JBKvayPN+6x4J8xgtI8kEPLZC+IAEFg7fnKCbMgdqecMqYn8kc+kYebosTnRL0ggVRMtVuALDaNH6g+1InpTg+gaI4yQopceMR4xo0FJ7ccmjq7CwvhLERoljnn08502xAaZaorh/ZMaCbbPscvS1WZg0u07bAvfJDppJbTpV1TW+v8RdT2GfY/Pe27hzklwvIk4HcxKW2oh+weR0j4fvtf3rdUhDFrIjLe5VPdrwIRKw0fAtowlzIk/ieu2oudSyki2bqL457Z4QOmPFKBC8aIt+LtQxbh7xfb3gAAAQAG2DjHpzzWGYtVLzMRfXwRFmVNwOO1Rg7ZmLjcy0hWy2b2JzeYJJSj+mRa/GC/Si3e16b0nBJGWU6FcTGSzPOdU3xrMJGLqtIlnUyqS5UJf75xs7zJamuSJ/QMLsvzqglaFBygL5Iuc5KF8lluXFK9h4ggCYxJp2UhgpsX6QMAl7ITeTHFdGWs/nwBHafEwxY3DViTmrj7wXuz8QBzzh65+lIrbOnibg3gliBg77bFLfVEFdylu3f5R18c8sZ9U0c4DOA+ZGlmAqSHZOQtyf8p8T+yKbMBJaQ/R+y0qG/R5Ai1d/aBcGZ1W5b/BU9Z+6yb7ITGowGzObBhU3L4g22e [email protected]`
}

expect(await validateConfig(piGenConfig)).toBeUndefined()
})
})
12 changes: 12 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@ inputs:
description: Enable SSH access to Pi.
required: false
default: 0
pubkey-ssh-first-user:
description: |
Setting this to a value will make that value the contents of the FIRST_USER_NAME's ~/.ssh/authorized_keys.
Obviously the value should therefore be a valid authorized_keys file. Note that this does not automatically
enable SSH.
required: false
pubkey-only-ssh:
description: |
Setting to `1` will disable password authentication for SSH and enable public key authentication. Note that if
SSH is not enabled this will take effect when SSH becomes enabled.
required: false
default: 0
docker-opts:
description: Additional options to include in PIGEN_DOCKER_OPTS
required: false
Expand Down
4 changes: 2 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module.exports = {
collectCoverageFrom: ['src/**/*.ts', '!src/misc/update-readme.ts'],
coverageThreshold: {
global: {
statements: 96,
branches: 91,
statements: 97,
branches: 92,
functions: 96,
lines: 97
}
Expand Down
8 changes: 3 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"@actions/glob": "^0.4.0",
"@actions/io": "^1.1.3",
"ansi-colors": "^4.1.3",
"json-colorizer": "^3.0.1"
"json-colorizer": "^3.0.1",
"tmp": "0.2.3"
},
"devDependencies": {
"@types/jest": "29.5.12",
Expand All @@ -58,7 +59,6 @@
"markdown-replace-section": "0.4.0",
"prettier": "3.2.5",
"semver": "7.6.0",
"tmp": "0.2.3",
"ts-jest": "29.1.2",
"ts-node": "10.9.2",
"typescript": "5.4.5",
Expand Down
3 changes: 3 additions & 0 deletions src/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export async function configure(): Promise<PiGenConfig> {
core.getInput('wpa-country') || DEFAULT_CONFIG.wpaCountry
userConfig.enableSsh =
core.getInput('enable-ssh') || DEFAULT_CONFIG.enableSsh
userConfig.pubkeySshFirstUser = core.getInput('pubkey-ssh-first-user')
userConfig.pubkeyOnlySsh =
core.getInput('pubkey-only-ssh') || DEFAULT_CONFIG.pubkeyOnlySsh
userConfig.enableNoobs =
core.getBooleanInput('enable-noobs')?.toString() ||
DEFAULT_CONFIG.enableNoobs
Expand Down
3 changes: 2 additions & 1 deletion src/host-dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export const hostDependencies = {
'qemu-user-static',
'qemu-utils',
'nbd-server',
'nbd-client'
'nbd-client',
'openssh-client'
],
modules: ['binfmt_misc', 'nbd']
}
30 changes: 30 additions & 0 deletions src/pi-gen-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as fs from 'fs/promises'
import * as tmp from 'tmp'
import {PiGenStages} from './pi-gen-stages'
import * as core from '@actions/core'
import * as exec from '@actions/exec'
Expand Down Expand Up @@ -172,6 +173,35 @@ export async function validateConfig(config: PiGenConfig): Promise<void> {
)
}

if (!/^[01]$/.test(config.enableSsh)) {
throw new Error(
`enable-ssh must be set to either "0" or "1" but was: ${config.enableSsh}`
)
}

if (!/^[01]$/.test(config.pubkeyOnlySsh)) {
throw new Error(
`pubkey-only-ssh must be set to either "0" or "1" but was: ${config.pubkeyOnlySsh}`
)
}

if (config.pubkeySshFirstUser) {
const tempAuthorizedKeysFile = tmp.fileSync()
await fs.writeFile(tempAuthorizedKeysFile.name, config.pubkeySshFirstUser)

const sshKeygenCmd = await io.which('ssh-keygen', true)
const sshKeygenOutput = await exec.getExecOutput(
sshKeygenCmd,
['-l', '-f', tempAuthorizedKeysFile.name],
{silent: true, ignoreReturnCode: true}
)
if (sshKeygenOutput.exitCode !== 0) {
throw new Error(
`pubkey-ssh-first-user does not seem to be a valid list of public key according to "ssh-keygen -l", here's its output:\n${sshKeygenOutput.stderr}`
)
}
}

if (!config.stageList || config.stageList.length === 0) {
throw new Error('stage-list must not be empty')
}
Expand Down

0 comments on commit 63ceb92

Please sign in to comment.