1 个不稳定版本

0.1.0 2024 年 7 月 13 日

#89身份验证

Download history 102/week @ 2024-07-08 9/week @ 2024-07-15 1/week @ 2024-07-29

112 次每月下载

Apache-2.0 OR MIT

360KB
5.5K SLoC

NetHSM 命令行界面

基于 nethsm crate 的 Nitrokey NetHSM 的命令行界面 (CLI)。

安装

该 crate 可以使用 cargo 安装。

cargo install nethsm-cli

之后,nethsm 可执行文件即可使用。

建议参考可执行文件及其子命令的详尽 --help 输出。

使用

以下假设有一个较新的 opensslpodman 版本。

启动测试容器

podman run --rm -ti --network=pasta:-t,auto,-u,auto,-T,auto,-U,auto docker.io/nitrokey/nethsm:testing

配置文件

配置文件使用 TOML 格式。

默认情况下,选择了一个特定于操作系统的、定义良好的配置文件位置。使用 -c / --config / NETHSM_CONFIG 环境变量,可以提供自定义配置文件位置。

# use a custom, temporary directory for all generated files
nethsm_tmpdir="$(mktemp --directory --suffix '.nethsm-test')"
# set a custom, temporary configuration file location
export NETHSM_CONFIG="$(mktemp --tmpdir="$nethsm_tmpdir" --suffix '-nethsm.toml' --dry-run)"

要与 NetHSM(或测试容器)交互,必须将每个设备添加到配置文件中。

# add the container using unsafe TLS connection handling for testing
nethsm env add device --label test https://127.0.0.1:8443/api/v1 Unsafe

如果仅配置了一个设备环境,则在发出 nethsm 命令时默认使用。如果配置了多个环境,则必须使用全局 -l / --label 选项选择目标设备。

凭据处理是灵活的:凭据可以带或不带密码短语存储在配置文件中,或者根本不存储。如果未配置凭据,将交互式提示输入。

# prepare a temporary passphrase file for the initial admin user passphrase
nethsm_admin_passphrase_file="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.admin-passphrase.txt')"
export NETHSM_PASSPHRASE_FILE="$nethsm_admin_passphrase_file"
printf 'my-very-unsafe-admin-passphrase' > "$NETHSM_PASSPHRASE_FILE"
# add the default admin user credentials
nethsm env add credentials admin Administrator

配置

在首次使用设备之前,必须对其进行配置。这包括设置初始 "admin" 用户的密码短语、解锁密码和设备系统时间。

# prepare a temporary passphrase file for the initial unlock passphrase
export NETHSM_UNLOCK_PASSPHRASE_FILE="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.unlock-passphrase.txt')"
printf 'my-very-unsafe-unlock-passphrase' > "$NETHSM_UNLOCK_PASSPHRASE_FILE"
# reuse the initial admin passphrase
export NETHSM_ADMIN_PASSPHRASE_FILE="$nethsm_admin_passphrase_file"
nethsm provision

用户

每个用户恰好可以属于一个角色("管理员"、"操作员"、"指标" 或 "备份")。

  • "管理员":用于调整系统配置、管理用户和密钥
  • "操作员":用于使用加密密钥和获取随机字节
  • "指标":用于检索设备的指标
  • "备份":用于创建和下载设备的备份
nethsm_admin1_passphrase_file="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.admin1-passphrase.txt')"
printf 'my-very-unsafe-admin1-passphrase' > "$nethsm_admin1_passphrase_file"
nethsm_operator1_passphrase_file="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.operator1-passphrase.txt')"
printf 'my-very-unsafe-operator1-passphrase' > "$nethsm_operator1_passphrase_file"
nethsm_backup1_passphrase_file="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.backup1-passphrase.txt')"
printf 'my-very-unsafe-backup1-passphrase' > "$nethsm_backup1_passphrase_file"
nethsm_metrics1_passphrase_file="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.metrics1-passphrase.txt')"
printf 'my-very-unsafe-metrics1-passphrase' > "$nethsm_metrics1_passphrase_file"

# we create a user in each role and add the credentials including passphrases to the configuration
# NOTE: this is for testing purposes! passphrases stored in configuration files can easily be retrieved!
export NETHSM_PASSPHRASE_FILE="$nethsm_admin1_passphrase_file"
nethsm user add "Some Admin1" Administrator admin1
nethsm env add credentials admin1 Administrator
export NETHSM_PASSPHRASE_FILE="$nethsm_operator1_passphrase_file"
nethsm user add "Some Operator1" Operator operator1
nethsm env add credentials operator1 Operator
export NETHSM_PASSPHRASE_FILE="$nethsm_backup1_passphrase_file"
nethsm user add "Some Backup1" Backup backup1
nethsm env add credentials backup1 Backup
export NETHSM_PASSPHRASE_FILE="$nethsm_metrics1_passphrase_file"
nethsm user add "Some Metrics1" Metrics metrics1
nethsm env add credentials metrics1 Metrics

可以查询用户名和相关信息

for user in $(nethsm user list); do
  nethsm user get "$user"
done

用户标签只能创建一次,当存在具有这些标签的密钥时。

密钥

设备上的密钥由“管理员”角色的用户管理。根据限制(标签),密钥也可能被“操作员”角色的用户使用。

生成密钥

以下生成所有可用类型的密钥(Curve25519、EcP224、EcP256、EcP384、EcP521、通用和Rsa)。在生成密钥时,可以手动设置其唯一ID(否则自动生成)。在生成密钥期间还可以设置标签,这些标签允许用户之后访问密钥。

请注意,某些密钥需要设置密钥位长度(即通用和Rsa)。

nethsm key generate --key-id signing1 --tags signing1 Curve25519 EdDsaSignature
nethsm key generate --key-id signing2 --tags signing2 EcP224 EcdsaSignature
nethsm key generate --key-id signing3 --tags signing2 EcP256 EcdsaSignature
nethsm key generate --key-id signing4 --tags signing2 EcP384 EcdsaSignature
nethsm key generate --key-id signing5 --tags signing2 EcP521 EcdsaSignature
nethsm key generate --key-id encdec1 --tags decryption1 --length 128 Generic AesDecryptionCbc AesEncryptionCbc
nethsm key generate --key-id dec1 --tags decryption2 --length 2048 Rsa RsaDecryptionPkcs1
nethsm key generate --key-id signing6 --tags signing3 --length 2048 Rsa RsaSignaturePssSha512

设备上所有密钥ID及其相关信息都可以列出

for key in $(nethsm key list); do
  nethsm key get "$key"
done

导入密钥

密钥也可以导入

ed25519_cert_pem="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.ed25519_cert.pem')"
ed25519_cert_der="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.ed25519_cert.pkcs8.der')"
openssl genpkey -algorithm ed25519 -out "$ed25519_cert_pem"
openssl pkcs8 -topk8 -inform pem -in "$ed25519_cert_pem" -outform der -nocrypt -out "$ed25519_cert_der"
# import requires a PKCS#8 private key in ASN.1 DER-encoded format
nethsm key import Curve25519 "$ed25519_cert_der" EdDsaSignature --key-id signing7

# forgot to set a tag!
nethsm key tag signing7 signing1

nethsm key get signing7

密钥访问

为了为用户提供密钥访问权限,用户必须带有与密钥相同的标签。

nethsm user tag operator1 signing1

签名消息

export NETHSM_KEY_SIGNATURE_OUTPUT_FILE="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.readme.signature.sig')"
export NETHSM_KEY_PUBKEY_OUTPUT_FILE="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.pubkey.pem')"
message_digest="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.message.dgst')"

# if we add the signing2 tag for operator1 it is able to use signing{2-5}
nethsm user tag operator1 signing2
# if we add the signing3 tag for operator1 it is able to use signing6
nethsm user tag operator1 signing3

# create a signature with each key type
nethsm key sign --force signing1 EdDsa README.md
nethsm key public-key --force signing1
openssl pkeyutl -verify -in README.md -rawin -sigfile "$NETHSM_KEY_SIGNATURE_OUTPUT_FILE" -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin

nethsm key sign --force signing2 EcdsaP224 README.md
nethsm key public-key --force signing2
openssl dgst -sha224 -binary README.md > "$message_digest"
openssl pkeyutl -verify -in "$message_digest" -sigfile "$NETHSM_KEY_SIGNATURE_OUTPUT_FILE" -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin

nethsm key sign --force signing3 EcdsaP256 README.md
nethsm key public-key --force signing3
openssl dgst -sha256 -binary README.md > "$message_digest"
openssl pkeyutl -verify -in "$message_digest" -sigfile "$NETHSM_KEY_SIGNATURE_OUTPUT_FILE" -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin

nethsm key sign --force signing4 EcdsaP384 README.md
nethsm key public-key --force signing4
openssl dgst -sha384 -binary README.md > "$message_digest"
openssl pkeyutl -verify -in "$message_digest" -sigfile "$NETHSM_KEY_SIGNATURE_OUTPUT_FILE" -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin

nethsm key sign --force signing5 EcdsaP521 README.md
nethsm key public-key --force signing5
openssl dgst -sha512 -binary README.md > "$message_digest"
openssl pkeyutl -verify -in "$message_digest" -sigfile "$NETHSM_KEY_SIGNATURE_OUTPUT_FILE" -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin

nethsm key sign --force signing6 PssSha512 README.md
nethsm key public-key --force signing6
openssl dgst -sha512 -binary README.md > "$message_digest"
openssl pkeyutl -verify -in "$message_digest" -sigfile "$NETHSM_KEY_SIGNATURE_OUTPUT_FILE" -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha512 -pkeyopt rsa_pss_saltlen:-1

nethsm key sign --force signing7 EdDsa README.md
nethsm key public-key --force signing7
openssl pkeyutl -verify -in README.md -rawin -sigfile "$NETHSM_KEY_SIGNATURE_OUTPUT_FILE" -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin

# if we remove the signing3 tag for operator1 it is no longer able to use signing6
nethsm user untag operator1 signing3

加密消息

可以使用提供此操作密钥机制的密钥加密消息。

message="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.message.txt')"
printf "Hello World! This is a message!!" > "$message"
export NETHSM_KEY_ENCRYPT_IV="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.iv.txt')"
printf "This is unsafe!!" > "$NETHSM_KEY_ENCRYPT_IV"
export NETHSM_KEY_ENCRYPT_OUTPUT="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.symmetric-encrypted-message.txt.enc')"

# we need to provide access to the key by tagging the user
nethsm user tag operator1 decryption1

# let's use our symmetric encryption key to encrypt a message
nethsm key encrypt encdec1 "$message"

# the initialization vector must be the same
export NETHSM_KEY_DECRYPT_IV="$NETHSM_KEY_ENCRYPT_IV"
export NETHSM_KEY_DECRYPT_OUTPUT="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.decrypted-message.txt')"
# now let's decrypt the encrypted message again
nethsm key decrypt encdec1 "$NETHSM_KEY_ENCRYPT_OUTPUT" AesCbc
cat "$NETHSM_KEY_DECRYPT_OUTPUT"

[[ "$(b2sum "$NETHSM_KEY_DECRYPT_OUTPUT" | cut -d ' ' -f1)" == "$(b2sum "$message" | cut -d ' ' -f1)" ]]

这对非对称密钥也适用

# we need to provide access to the key by tagging the user
nethsm user tag operator1 decryption2

# unset the initialization vectors as we do not need them for this
unset NETHSM_KEY_DECRYPT_IV NETHSM_KEY_ENCRYPT_IV
# retrieve the public key of the key to use (and overwrite any previously existing)
nethsm key public-key --force dec1

asymmetric_enc_message="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.asymmetric-encrypted-message.txt.enc')"
# encrypt the previous message
openssl pkeyutl -encrypt -inkey "$NETHSM_KEY_PUBKEY_OUTPUT_FILE" -pubin -in "$message" -out "$asymmetric_enc_message"

# decrypt the asymmetrically encrypted message and replace any existing output
nethsm key decrypt dec1 "$asymmetric_enc_message" Pkcs1 --force
cat "$NETHSM_KEY_DECRYPT_OUTPUT"

[[ "$(b2sum "$NETHSM_KEY_DECRYPT_OUTPUT" | cut -d ' ' -f1)" == "$(b2sum "$message" | cut -d ' ' -f1)" ]]

公钥

管理员和操作员可以检索任何密钥的公钥

# keys of type "Generic" don't have a public key, so we do not request them
for key in signing{1..7} dec1; do
  nethsm key public-key "$key" --force
done

密钥的证书签名请求

可以使用密钥发布特定目标的证书签名请求。

# get a CSR for example.com
nethsm key csr signing7 example.com

随机字节

设备可以按需生成任意数量的随机字节。

export NETHSM_RANDOM_OUTPUT_FILE="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.random.txt')"
nethsm random 200

[[ -f "$NETHSM_RANDOM_OUTPUT_FILE" ]]

指标

只有“指标”角色的用户才能检索设备的指标。

nethsm metrics

设备配置

可以检索和修改设备配置的多个方面。

启动模式

启动模式定义系统是否进入“锁定”或“操作”状态(前者需要提供解锁密码才能进入“操作”状态)。

nethsm config get boot-mode

# let's set it to unattended
nethsm config set boot-mode Unattended

nethsm config get boot-mode

日志记录

每个设备都可以将syslog发送到远程主机。

nethsm config get logging

网络

设备具有唯一和静态的网络配置。

nethsm config get network

系统时间

可以查询和设置设备的系统时间。

nethsm config get time
nethsm config set time
nethsm config get time

TLS证书

可以获取和设置设备使用的TLS证书。

nethsm config get tls-certificate
# this generates a new RSA 4096bit certificate on the device
nethsm config set tls-generate Rsa 4096
nethsm config get tls-certificate

也可以只接收TLS证书的公钥

nethsm config get tls-public-key

或为TLS证书生成证书签名请求

nethsm config get tls-csr example.com

设置密码短语

备份密码短语用于在导入时解密为设备创建的备份。默认情况下为空字符串("")。

nethsm_backup_passphrase_file="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.backup-passphrase.txt')"
printf 'my-very-unsafe-backup-passphrase' > "$nethsm_backup_passphrase_file"
export NETHSM_NEW_PASSPHRASE_FILE="$nethsm_backup_passphrase_file"
nethsm_initial_backup_passphrase_file="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.initial-backup-passphrase.txt')"
touch "$nethsm_initial_backup_passphrase_file"
export NETHSM_OLD_PASSPHRASE_FILE="$nethsm_initial_backup_passphrase_file"
nethsm config set backup-passphrase

解锁密码在初始配置期间设置,并在设备锁定时解锁设备。

export NETHSM_OLD_PASSPHRASE_FILE="$NETHSM_UNLOCK_PASSPHRASE_FILE"
export NETHSM_NEW_PASSPHRASE_FILE="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.unlock-passphrase.txt')"
printf 'my-new-unsafe-unlock-passphrase' > "$NETHSM_NEW_PASSPHRASE_FILE"
nethsm config set unlock-passphrase

锁定

设备可以锁定和解锁,将其置于“锁定”和“操作”状态(分别对应于"Locked""Operational")。

nethsm lock
nethsm health state
nethsm health alive
# as we have changed the unlock passphrase, we need to provide the new one
export NETHSM_UNLOCK_PASSPHRASE_FILE="$NETHSM_NEW_PASSPHRASE_FILE"
nethsm unlock
nethsm health state
nethsm health ready

系统修改

设备提供各种系统级操作,例如。

# reset device to factory settings
nethsm system factory-reset
# reboot device
nethsm system reboot
# shut down device
nethsm system shutdown
# get system info about the device
nethsm system info

备份

设备提供密钥和用户数据的备份。

export NETHSM_BACKUP_OUTPUT_FILE="$(mktemp --tmpdir="$nethsm_tmpdir" --dry-run --suffix '-nethsm.backup-file.bkp')"
nethsm system backup

备份之后可以用来恢复设备

export NETHSM_BACKUP_PASSPHRASE_FILE="$nethsm_backup_passphrase_file"
nethsm system restore "$NETHSM_BACKUP_OUTPUT_FILE"

更新

将设备操作系统的/固件更新上传到设备,然后应用或取消。

nethsm system upload-update my-update-file.bin
# apply the update
nethsm system commit-update
# abort the update
nethsm system cancel-update
rm -r -- "$nethsm_tmpdir"

许可协议

本项目可以在Apache-2.0MIT许可协议的条款下使用。

除非另有声明,否则对本项目的修改自动适用于上述两种许可协议的条款。

依赖项

~22-36MB
~669K SLoC