mirror of
https://github.com/kairos-io/kcrypt.git
synced 2025-11-04 20:05:22 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c08c563658 | ||
|
|
47e7f67e04 | ||
|
|
f5dc23f554 | ||
|
|
2889a52eab | ||
|
|
18eab4843d | ||
|
|
3e25056dd0 | ||
|
|
36f861fd0c | ||
|
|
5f52d1f2f9 | ||
|
|
7a8210d26c | ||
|
|
6d6dfd00a1 | ||
|
|
92c79f4e75 | ||
|
|
a254871c22 | ||
|
|
7e6a31f38b | ||
|
|
0f3eee7851 | ||
|
|
15cc284978 | ||
|
|
b7352829ff | ||
|
|
57aef89b02 | ||
|
|
2dbd13c984 | ||
|
|
ff42570ec7 | ||
|
|
36fafa38cf | ||
|
|
f977f72e8d | ||
|
|
608b465afc | ||
|
|
79fbcc2f73 | ||
|
|
7298e9c0dd | ||
|
|
94cfbcfe88 | ||
|
|
1296f284cb | ||
|
|
4cff0323af | ||
|
|
9c7c27af89 | ||
|
|
fa9eb79998 | ||
|
|
11bfa53dc1 | ||
|
|
930d7433ae | ||
|
|
845f5984b1 | ||
|
|
71506ff020 | ||
|
|
27183fbce7 | ||
|
|
018322ff00 | ||
|
|
361e1ab817 | ||
|
|
4234ae7034 | ||
|
|
193a7da9ee | ||
|
|
e0316ade0a | ||
|
|
1c3a3ac510 | ||
|
|
641fc6ffa7 | ||
|
|
214ae51333 | ||
|
|
7f397a3459 | ||
|
|
b3d7b86591 | ||
|
|
24240b6421 | ||
|
|
bb144f204a |
28
.github/workflows/lint.yaml
vendored
Normal file
28
.github/workflows/lint.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
- name: Install earthly
|
||||
uses: Luet-lab/luet-install-action@v1
|
||||
with:
|
||||
repository: quay.io/kairos/packages
|
||||
packages: utils/earthly
|
||||
- name: Run Lint checks
|
||||
run: |
|
||||
earthly +lint
|
||||
10
.github/workflows/unit-tests.yml
vendored
10
.github/workflows/unit-tests.yml
vendored
@@ -1,9 +1,9 @@
|
||||
name: Unit tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.18'
|
||||
go-version: '^1.20'
|
||||
|
||||
- name: Install Ginkgo
|
||||
run: go install github.com/onsi/ginkgo/v2/ginkgo@v2.5.0
|
||||
|
||||
21
.yamllint
Normal file
21
.yamllint
Normal file
@@ -0,0 +1,21 @@
|
||||
extends: default
|
||||
|
||||
rules:
|
||||
# 80 chars should be enough, but don't fail if a line is longer
|
||||
line-length:
|
||||
max: 150
|
||||
level: warning
|
||||
|
||||
# accept both key:
|
||||
# - item
|
||||
#
|
||||
# and key:
|
||||
# - item
|
||||
indentation:
|
||||
indent-sequences: whatever
|
||||
|
||||
truthy:
|
||||
check-keys: false
|
||||
|
||||
document-start:
|
||||
present: false
|
||||
38
Earthfile
38
Earthfile
@@ -3,6 +3,9 @@ VERSION 0.6
|
||||
# TODO: This needs to come from pre-built kernels in c3os repos, kcrypt included.
|
||||
# Framework images should use our initrd
|
||||
ARG BASE_IMAGE=quay.io/kairos/core-opensuse
|
||||
# renovate: datasource=docker depName=golang
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG GOLINT_VERSION=1.52.2
|
||||
|
||||
build-kcrypt:
|
||||
FROM golang:alpine
|
||||
@@ -11,15 +14,22 @@ build-kcrypt:
|
||||
WORKDIR /work
|
||||
ARG VERSION="$(git describe --tags)"
|
||||
RUN CGO_ENABLED=0 go build -o kcrypt -ldflags "-X main.Version=$VERSION"
|
||||
SAVE ARTIFACT /work/kcrypt AS LOCAL kcrypt
|
||||
SAVE ARTIFACT /work/kcrypt kcrypt AS LOCAL kcrypt
|
||||
|
||||
dracut-artifacts:
|
||||
FROM $BASE_IMAGE
|
||||
WORKDIR /build
|
||||
COPY --dir dracut/29kcrypt .
|
||||
COPY dracut/10-kcrypt.conf .
|
||||
SAVE ARTIFACT 29kcrypt 29kcrypt
|
||||
SAVE ARTIFACT 10-kcrypt.conf 10-kcrypt.conf
|
||||
|
||||
build-dracut:
|
||||
FROM $BASE_IMAGE
|
||||
COPY . /work
|
||||
COPY +build-kcrypt/kcrypt /usr/bin/kcrypt
|
||||
WORKDIR /work
|
||||
RUN cp -r dracut/* /usr/lib/dracut/modules.d
|
||||
RUN cp dracut.conf /etc/dracut.conf.d/10-kcrypt.conf
|
||||
COPY +build-kcrypt/kcrypt /usr/bin/kcrypt
|
||||
COPY +dracut-artifacts/29kcrypt /usr/lib/dracut/modules.d/29kcrypt
|
||||
COPY +dracut-artifacts/10-kcrypt.conf /etc/dracut.conf.d/10-kcrypt.conf
|
||||
RUN kernel=$(ls /lib/modules | head -n1) && \
|
||||
dracut -f "/boot/initrd-${kernel}" "${kernel}" && \
|
||||
ln -sf "initrd-${kernel}" /boot/initrd
|
||||
@@ -63,3 +73,21 @@ iso:
|
||||
RUN sha256sum $ISO_NAME.iso > $ISO_NAME.iso.sha256
|
||||
SAVE ARTIFACT /build/$ISO_NAME.iso iso AS LOCAL build/$ISO_NAME.iso
|
||||
SAVE ARTIFACT /build/$ISO_NAME.iso.sha256 sha256 AS LOCAL build/$ISO_NAME.iso.sha256
|
||||
|
||||
lint:
|
||||
BUILD +golint
|
||||
BUILD +yamllint
|
||||
|
||||
golint:
|
||||
ARG GO_VERSION
|
||||
FROM golang:$GO_VERSION
|
||||
ARG GOLINT_VERSION
|
||||
RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v$GOLINT_VERSION
|
||||
WORKDIR /build
|
||||
COPY . .
|
||||
RUN golangci-lint run
|
||||
|
||||
yamllint:
|
||||
FROM cytopia/yamllint
|
||||
COPY . .
|
||||
RUN yamllint .github/workflows/
|
||||
|
||||
64
README.md
Normal file
64
README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<img width="184" alt="kairos-white-column 5bc2fe34" src="https://user-images.githubusercontent.com/2420543/193010398-72d4ba6e-7efe-4c2e-b7ba-d3a826a55b7d.png"><br>
|
||||
Kcrypt
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
<h3 align="center">Cloud native guardian for persistent data in the edge</h3>
|
||||
<p align="center">
|
||||
<a href="https://opensource.org/licenses/">
|
||||
<img src="https://img.shields.io/badge/licence-APL2-brightgreen"
|
||||
alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/kairos-io/kcrypt/issues"><img src="https://img.shields.io/github/issues/kairos-io/kcrypt"></a>
|
||||
<a href="https://kairos.io/docs/" target=_blank> <img src="https://img.shields.io/badge/Documentation-blue"
|
||||
alt="docs"></a>
|
||||
<img src="https://img.shields.io/badge/made%20with-Go-blue">
|
||||
<img src="https://goreportcard.com/badge/github.com/kairos-io/kcrypt" alt="go report card" />
|
||||
</p>
|
||||
|
||||
|
||||
With Kairos you can build immutable, bootable Kubernetes and OS images for your edge devices as easily as writing a Dockerfile. Optional P2P mesh with distributed ledger automates node bootstrapping and coordination. Updating nodes is as easy as CI/CD: push a new image to your container registry and let secure, risk-free A/B atomic upgrades do the rest.
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th align="center">
|
||||
<img width="640" height="1px">
|
||||
<p>
|
||||
<small>
|
||||
Documentation
|
||||
</small>
|
||||
</p>
|
||||
</th>
|
||||
<th align="center">
|
||||
<img width="640" height="1">
|
||||
<p>
|
||||
<small>
|
||||
Contribute
|
||||
</small>
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
📚 [Getting started with Kairos](https://kairos.io/docs/getting-started) <br> :bulb: [Examples](https://kairos.io/docs/examples) <br> :movie_camera: [Video](https://kairos.io/docs/media/) <br> :open_hands:[Engage with the Community](https://kairos.io/community/)
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
🙌[ CONTRIBUTING.md ]( https://github.com/kairos-io/kairos/blob/master/CONTRIBUTING.md ) <br> :raising_hand: [ GOVERNANCE ]( https://github.com/kairos-io/kairos/blob/master/GOVERNANCE.md ) <br>:construction_worker:[Code of conduct](https://github.com/kairos-io/kairos/blob/master/CODE_OF_CONDUCT.md)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Description
|
||||
|
||||
This is the Kairos internal component which delegates encryption and decryption of partitions in a Kairos system.
|
||||
|
||||
## Usage
|
||||
|
||||
See the documentation in our website: https://kairos.io/docs/advanced/partition_encryption/.
|
||||
@@ -7,34 +7,46 @@ GENERATOR_DIR="$2"
|
||||
[ -z "$GENERATOR_DIR" ] && exit 1
|
||||
[ -d "$GENERATOR_DIR" ] || mkdir "$GENERATOR_DIR"
|
||||
|
||||
if getargbool 0 rd.neednet; then
|
||||
{
|
||||
echo "[Unit]"
|
||||
echo "DefaultDependencies=no"
|
||||
echo "Description=kcrypt online mount"
|
||||
echo "Before=cos-immutable-rootfs.service"
|
||||
echo "After=network-online.target"
|
||||
echo "Wants=network-online.target"
|
||||
echo "[Service]"
|
||||
echo "Type=oneshot"
|
||||
echo "RemainAfterExit=no"
|
||||
echo "ExecStart=/sbin/kcrypt-mount-local"
|
||||
} > "$GENERATOR_DIR"/kcrypt.service
|
||||
else
|
||||
{
|
||||
echo "[Unit]"
|
||||
echo "DefaultDependencies=no"
|
||||
echo "Description=kcrypt mount"
|
||||
echo "Before=cos-immutable-rootfs.service"
|
||||
echo "[Service]"
|
||||
echo "Type=oneshot"
|
||||
echo "RemainAfterExit=no"
|
||||
echo "ExecStart=/sbin/kcrypt-mount-local"
|
||||
} > "$GENERATOR_DIR"/kcrypt.service
|
||||
oem_label=$(getarg rd.cos.oemlabel=)
|
||||
|
||||
## Several things indicate booting from a different media so we should not do anything
|
||||
## rd.cos.disable is set on LIVECD and disables mounting of any type
|
||||
if getargbool 0 rd.cos.disable; then
|
||||
exit 0
|
||||
fi
|
||||
## Netboot is set on...well, netboot obiously
|
||||
if getargbool 0 netboot; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
# See https://github.com/kairos-io/packages/blob/d12b12b043a71d8471454f7b4fc84c3181d2bf60/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-generator.sh#L29
|
||||
{
|
||||
echo "[Unit]"
|
||||
echo "DefaultDependencies=no"
|
||||
echo "Before=immucore.service"
|
||||
echo "Conflicts=initrd-switch-root.target"
|
||||
if getargbool 0 rd.neednet; then
|
||||
echo "Wants=network-online.target"
|
||||
echo "After=network-online.target"
|
||||
echo "Description=kcrypt online mount"
|
||||
else
|
||||
echo "Description=kcrypt mount"
|
||||
fi
|
||||
# OEM is special as kcrypt plugins might need that in order to unlock other partitions and plugins can reside in /oem as well and kcrypt needs to find them
|
||||
if [ -n "${oem_label}" ]; then
|
||||
echo "After=oem.mount"
|
||||
fi
|
||||
echo "After=sysroot.mount"
|
||||
echo "[Service]"
|
||||
echo "Type=oneshot"
|
||||
echo "RemainAfterExit=no"
|
||||
echo "ExecStart=/usr/bin/kcrypt unlock-all"
|
||||
} > "$GENERATOR_DIR"/kcrypt.service
|
||||
|
||||
|
||||
if [ ! -e "$GENERATOR_DIR/initrd-fs.target.requires/kcrypt.service" ]; then
|
||||
mkdir -p "$GENERATOR_DIR"/initrd-fs.target.requires
|
||||
ln -s "$GENERATOR_DIR"/kcrypt.service \
|
||||
"$GENERATOR_DIR"/initrd-fs.target.requires/kcrypt.service
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -27,8 +27,7 @@ install() {
|
||||
|
||||
inst_multiple \
|
||||
kcrypt
|
||||
inst_script "${moddir}/mount-local.sh" "/sbin/kcrypt-mount-local"
|
||||
#inst_hook pre-trigger 10 "$moddir/mount-local.sh"
|
||||
|
||||
inst_script "${moddir}/generator.sh" \
|
||||
"${systemdutildir}/system-generators/dracut-kcrypt-generator"
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||
|
||||
type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
|
||||
|
||||
PATH=/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
OEM=$(blkid -L COS_OEM)
|
||||
if [ "$OEM" != "" ]; then
|
||||
mkdir /oem
|
||||
mount $OEM /oem
|
||||
fi
|
||||
|
||||
kcrypt unlock-all
|
||||
|
||||
if [ "$OEM" != "" ]; then
|
||||
umount /oem
|
||||
fi
|
||||
3
earthly.sh
Executable file
3
earthly.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker run --privileged -v /var/run/docker.sock:/var/run/docker.sock --rm -t -v $(pwd):/workspace -v earthly-tmp:/tmp/earthly:rw earthly/earthly:v0.6.21 --allow-privileged $@
|
||||
67
go.mod
67
go.mod
@@ -1,38 +1,69 @@
|
||||
module github.com/kairos-io/kcrypt
|
||||
|
||||
go 1.18
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/anatol/luks.go v0.0.0-20220803222236-155595903818
|
||||
github.com/anatol/luks.go v0.0.0-20230125211543-ada2562d4206
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/jaypipes/ghw v0.9.0
|
||||
github.com/mudler/go-pluggable v0.0.0-20220716112424-189d463e3ff3
|
||||
github.com/onsi/ginkgo/v2 v2.5.0
|
||||
github.com/onsi/gomega v1.24.0
|
||||
github.com/otiai10/copy v1.7.0
|
||||
github.com/jaypipes/ghw v0.10.0
|
||||
github.com/kairos-io/kairos v1.24.3-56.0.20230329142538-b6ae4b58c07d
|
||||
github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5
|
||||
github.com/onsi/ginkgo/v2 v2.9.2
|
||||
github.com/onsi/gomega v1.27.5
|
||||
github.com/otiai10/copy v1.9.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/urfave/cli v1.22.9
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
github.com/urfave/cli v1.22.12
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0
|
||||
)
|
||||
|
||||
require (
|
||||
atomicgo.dev/cursor v0.1.1 // indirect
|
||||
atomicgo.dev/keyboard v0.2.9 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/anatol/devmapper.go v0.0.0-20220716012224-693a1447fc15 // indirect
|
||||
github.com/anatol/devmapper.go v0.0.0-20220907161421-ba4de5fc0fd1 // indirect
|
||||
github.com/avast/retry-go v3.0.0+incompatible // indirect
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect
|
||||
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/denisbrodbeck/machineid v1.0.1 // indirect
|
||||
github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/gookit/color v1.5.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/itchyny/gojq v0.12.12 // indirect
|
||||
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
||||
github.com/jaypipes/pcidb v1.0.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/kairos-io/kairos-sdk v0.0.2-0.20230317135804-ad3c0f6cd6dd // indirect
|
||||
github.com/kr/text v0.1.0 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.5 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||
golang.org/x/net v0.1.0 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/pterm/pterm v0.12.57 // indirect
|
||||
github.com/qeesung/image2ascii v1.0.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/term v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
howett.net/plist v1.0.0 // indirect
|
||||
)
|
||||
|
||||
198
go.sum
198
go.sum
@@ -1,19 +1,43 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
atomicgo.dev/cursor v0.1.1 h1:0t9sxQomCTRh5ug+hAMCs59x/UmC9QL6Ci5uosINKD4=
|
||||
atomicgo.dev/cursor v0.1.1/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
|
||||
atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
|
||||
atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
|
||||
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
|
||||
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
|
||||
github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k=
|
||||
github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
|
||||
github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
|
||||
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/anatol/devmapper.go v0.0.0-20220716012224-693a1447fc15 h1:741Z9HQjbLXe4SnZ6liQTYINeD559oFl/vOtzA21KM0=
|
||||
github.com/anatol/devmapper.go v0.0.0-20220716012224-693a1447fc15/go.mod h1:Ow7/kdG1m4K6UDTOwJeYJv9bkSLoL44qSu7S/Bxxi4Y=
|
||||
github.com/anatol/luks.go v0.0.0-20220803222236-155595903818 h1:IyYgXFMhnSIbkDnDrTnMrPDYlc/uYhG5UcGX6NVkO58=
|
||||
github.com/anatol/luks.go v0.0.0-20220803222236-155595903818/go.mod h1:1lE8PgTi0cS+3YsxbWcpfvGfjiPrRdcKJZc9j70OOTs=
|
||||
github.com/anatol/devmapper.go v0.0.0-20220907161421-ba4de5fc0fd1 h1:6ok4FQsJFooNYKiSmrVUv476cG/NYmbM0LxazuL4sZU=
|
||||
github.com/anatol/devmapper.go v0.0.0-20220907161421-ba4de5fc0fd1/go.mod h1:k5R4Ie9eQbP4muJljLeun3f1onpMKRSqG/aXMFdCWm4=
|
||||
github.com/anatol/luks.go v0.0.0-20230125211543-ada2562d4206 h1:9kfvAJRm75SuSR185WrbYOco0cKFo9IglQfiFyRNvK0=
|
||||
github.com/anatol/luks.go v0.0.0-20230125211543-ada2562d4206/go.mod h1:XwLorksvNshI9TH9UOO/WfX7kYIdlljCQi5WPkN7K0c=
|
||||
github.com/anatol/vmtest v0.0.0-20220413190228-7a42f1f6d7b8 h1:t4JGeY9oaF5LB4Rdx9e2wARRRPAYt8Ow4eCf5SwO3fA=
|
||||
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
|
||||
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 h1:xz6Nv3zcwO2Lila35hcb0QloCQsc38Al13RNEzWRpX4=
|
||||
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9/go.mod h1:2wSM9zJkl1UQEFZgSd68NfCgRz1VL1jzy/RjCg+ULrs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
|
||||
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
|
||||
github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d h1:CPqTNIigGweVPT4CYb+OO2E6XyRKFOmvTHwWRLgCAlE=
|
||||
github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d/go.mod h1:QX5ZVULjAfZJux/W62Y91HvCh9hyW6enAwcrrv/sLj0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
@@ -21,6 +45,10 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
@@ -28,78 +56,136 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso=
|
||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
|
||||
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
|
||||
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jaypipes/ghw v0.9.0 h1:TWF4wNIGtZcgDJaiNcFgby5BR8s2ixcUe0ydxNO2McY=
|
||||
github.com/jaypipes/ghw v0.9.0/go.mod h1:dXMo19735vXOjpIBDyDYSp31sB2u4hrtRCMxInqQ64k=
|
||||
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
|
||||
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/itchyny/gojq v0.12.12 h1:x+xGI9BXqKoJQZkr95ibpe3cdrTbY8D9lonrK433rcA=
|
||||
github.com/itchyny/gojq v0.12.12/go.mod h1:j+3sVkjxwd7A7Z5jrbKibgOLn0ZfLWkV+Awxr/pyzJE=
|
||||
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
||||
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
||||
github.com/jaypipes/ghw v0.10.0 h1:UHu9UX08Py315iPojADFPOkmjTsNzHj4g4adsNKKteY=
|
||||
github.com/jaypipes/ghw v0.10.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g=
|
||||
github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
|
||||
github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/kairos-io/kairos v1.24.3-56.0.20230329142538-b6ae4b58c07d h1:B01GinEZbowPwbWrqDIb6n2AaHIscJVOqsh0I5gAEXw=
|
||||
github.com/kairos-io/kairos v1.24.3-56.0.20230329142538-b6ae4b58c07d/go.mod h1:2aYSSCHw8csfuqA5g6BpxBJ89kZt84G5okeuJj7PH+w=
|
||||
github.com/kairos-io/kairos-sdk v0.0.2-0.20230317135804-ad3c0f6cd6dd h1:x3pwiwfj/eAv3OZ8BNFdmpjhh8ZInu7z8Xv/6+dhmFw=
|
||||
github.com/kairos-io/kairos-sdk v0.0.2-0.20230317135804-ad3c0f6cd6dd/go.mod h1:Wg/jfAQe8seka5VUXtcPvg+sA6GmQEy+DYlJmgKM8Zs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
|
||||
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mudler/go-pluggable v0.0.0-20220716112424-189d463e3ff3 h1:t4X6t8WisUy5mExfS58RBOkzaEGmuor5kOUMQS8lT2g=
|
||||
github.com/mudler/go-pluggable v0.0.0-20220716112424-189d463e3ff3/go.mod h1:WmKcT8ONmhDQIqQ+HxU+tkGWjzBEyY/KFO8LTGCu4AI=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5 h1:FaZD86+A9mVt7lh9glAryzQblMsbJYU2VnrdZ8yHlTs=
|
||||
github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5/go.mod h1:WmKcT8ONmhDQIqQ+HxU+tkGWjzBEyY/KFO8LTGCu4AI=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls=
|
||||
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU=
|
||||
github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
|
||||
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||
github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
|
||||
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
|
||||
github.com/onsi/gomega v1.27.5 h1:T/X6I0RNFw/kTqgfkZPcQ5KU6vCnWNBGdtrIx2dpGeQ=
|
||||
github.com/onsi/gomega v1.27.5/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4=
|
||||
github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI=
|
||||
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
||||
github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4=
|
||||
github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
|
||||
github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
|
||||
github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
|
||||
github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU=
|
||||
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
|
||||
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
|
||||
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
|
||||
github.com/pterm/pterm v0.12.57 h1:HTjDUmILmh6hIsEidRdpxQAiqcoHCdvRCxIR3KZ0/XE=
|
||||
github.com/pterm/pterm v0.12.57/go.mod h1:7rswprkyxYOse1IMh79w42jvReNHxro4z9oHfqjIdzM=
|
||||
github.com/qeesung/image2ascii v1.0.1 h1:Fe5zTnX/v/qNC3OC4P/cfASOXS501Xyw2UUcgrLgtp4=
|
||||
github.com/qeesung/image2ascii v1.0.1/go.mod h1:kZKhyX0h2g/YXa/zdJR3JnLnJ8avHjZ3LrvEKSYyAyU=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef h1:7D6Nm4D6f0ci9yttWaKjM1TMAXrH5Su72dojqYGntFY=
|
||||
github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw=
|
||||
github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8=
|
||||
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
|
||||
github.com/wayneashleyberry/terminal-dimensions v1.1.0 h1:EB7cIzBdsOzAgmhTUtTTQXBByuPheP/Zv1zL2BRPY6g=
|
||||
github.com/wayneashleyberry/terminal-dimensions v1.1.0/go.mod h1:2lc/0eWCObmhRczn2SdGSQtgBooLUzIotkkEGXqghyg=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -111,15 +197,30 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@@ -127,19 +228,22 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU=
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
|
||||
132
main.go
132
main.go
@@ -2,31 +2,30 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
luks "github.com/anatol/luks.go"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/jaypipes/ghw"
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kcrypt/pkg/bus"
|
||||
"github.com/mudler/go-pluggable"
|
||||
configpkg "github.com/kairos-io/kcrypt/pkg/config"
|
||||
"github.com/kairos-io/kcrypt/pkg/lib"
|
||||
cp "github.com/otiai10/copy"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
pi "github.com/kairos-io/kcrypt/pkg/partition_info"
|
||||
)
|
||||
|
||||
var Version = "v0.0.0-dev"
|
||||
|
||||
func waitdevice(device string, attempts int) error {
|
||||
for tries := 0; tries < attempts; tries++ {
|
||||
sh("udevadm settle")
|
||||
_, err := os.Lstat(device)
|
||||
_, err := sh("udevadm settle")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = os.Lstat(device)
|
||||
if !os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
@@ -35,49 +34,6 @@ func waitdevice(device string, attempts int) error {
|
||||
return fmt.Errorf("no device found")
|
||||
}
|
||||
|
||||
// TODO: Ask to discovery a pass to unlock. keep waiting until we get it and a timeout is exhausted with retrials (exp backoff)
|
||||
func getPassword(b *block.Partition) (password string, err error) {
|
||||
bus.Reload()
|
||||
|
||||
bus.Manager.Response(bus.EventDiscoveryPassword, func(p *pluggable.Plugin, r *pluggable.EventResponse) {
|
||||
password = r.Data
|
||||
if r.Errored() {
|
||||
err = fmt.Errorf("failed discovery: %s", r.Error)
|
||||
}
|
||||
})
|
||||
bus.Manager.Publish(bus.EventDiscoveryPassword, b)
|
||||
|
||||
if password == "" {
|
||||
return password, fmt.Errorf("received empty password")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func luksUnlock(device, mapper, password string) error {
|
||||
dev, err := luks.Open(device)
|
||||
if err != nil {
|
||||
// handle error
|
||||
return err
|
||||
}
|
||||
defer dev.Close()
|
||||
|
||||
err = dev.Unlock(0, []byte(password), mapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unlockDisk(b *block.Partition) error {
|
||||
pass, err := getPassword(b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retreiving password remotely: %w", err)
|
||||
}
|
||||
|
||||
return luksUnlock(fmt.Sprintf("/dev/%s", b.Name), b.Name, pass)
|
||||
}
|
||||
|
||||
func createLuks(dev, password, version string, cryptsetupArgs ...string) error {
|
||||
if version == "" {
|
||||
version = "luks2"
|
||||
@@ -88,27 +44,14 @@ func createLuks(dev, password, version string, cryptsetupArgs ...string) error {
|
||||
cmd.Stdin = strings.NewReader(password)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createDiskImage() (*os.File, error) {
|
||||
disk, err := ioutil.TempFile("", "luksv2.go.disk")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := disk.Truncate(24 * 1024 * 1024); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return disk, err
|
||||
}
|
||||
|
||||
// TODO: A crypt disk utility to call after install, that with discovery discoveries the password that should be used
|
||||
// this function should delete COS_PERSISTENT. delete the partition and create a luks+type in place.
|
||||
|
||||
@@ -125,19 +68,20 @@ func luksify(label string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pass, err := getPassword(b)
|
||||
pass, err := lib.GetPassword(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
persistent = fmt.Sprintf("/dev/%s", persistent)
|
||||
devMapper := fmt.Sprintf("/dev/mapper/%s", b.Name)
|
||||
partUUID := uuid.NewV5(uuid.NamespaceURL, label)
|
||||
|
||||
if err := createLuks(persistent, pass, "luks1"); err != nil {
|
||||
if err := createLuks(persistent, pass, "luks1", []string{"--uuid", partUUID.String()}...); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := luksUnlock(persistent, b.Name, pass); err != nil {
|
||||
if err := lib.LuksUnlock(persistent, b.Name, pass); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -145,8 +89,8 @@ func luksify(label string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
out, err := sh(fmt.Sprintf("mkfs.ext4 -L %s %s", label, devMapper))
|
||||
|
||||
cmd := fmt.Sprintf("mkfs.ext4 -L %s %s", label, devMapper)
|
||||
out, err := sh(cmd)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("err: %w, out: %s", err, out)
|
||||
}
|
||||
@@ -156,15 +100,15 @@ func luksify(label string) (string, error) {
|
||||
return "", fmt.Errorf("err: %w, out: %s", err, out2)
|
||||
}
|
||||
|
||||
return pi.PartitionToString(b), nil
|
||||
return configpkg.PartitionToString(b), nil
|
||||
}
|
||||
|
||||
func findPartition(label string) (string, *block.Partition, error) {
|
||||
block, err := ghw.Block()
|
||||
b, err := ghw.Block()
|
||||
if err == nil {
|
||||
for _, disk := range block.Disks {
|
||||
for _, disk := range b.Disks {
|
||||
for _, p := range disk.Partitions {
|
||||
if p.Label == label {
|
||||
if p.FilesystemLabel == label {
|
||||
return p.Name, p, nil
|
||||
}
|
||||
|
||||
@@ -211,9 +155,13 @@ func detect(archive string) (string, error) {
|
||||
|
||||
// TODO: replace with golang native code
|
||||
func extractInitrd(initrd string, dst string) error {
|
||||
os.MkdirAll(dst, os.ModePerm)
|
||||
var out string
|
||||
var err error
|
||||
err = os.MkdirAll(dst, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
format, err := detect(initrd)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -257,7 +205,7 @@ func injectInitrd(initrd string, file, dst string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp, err := ioutil.TempDir("", "kcrypt")
|
||||
tmp, err := os.MkdirTemp("", "kcrypt")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create tempdir, %s", err)
|
||||
}
|
||||
@@ -278,32 +226,6 @@ func injectInitrd(initrd string, file, dst string) error {
|
||||
}
|
||||
|
||||
// TODO: a custom toolkit version, to build out initrd pre-built with this component
|
||||
func unlockAll() error {
|
||||
bus.Manager.Initialize()
|
||||
|
||||
partitionInfo, _, err := pi.NewPartitionInfoFromFile(pi.DefaultPartitionInfoFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
block, err := ghw.Block()
|
||||
if err == nil {
|
||||
for _, disk := range block.Disks {
|
||||
for _, p := range disk.Partitions {
|
||||
if p.Type == "crypto_LUKS" {
|
||||
p.Label = partitionInfo.LookupLabelForUUID(p.UUID)
|
||||
fmt.Printf("Unmounted Luks found at '%s' LABEL '%s' \n", p.Name, p.Label)
|
||||
err = multierror.Append(err, unlockDisk(p))
|
||||
if err != nil {
|
||||
fmt.Printf("Unlocking failed: '%s'\n", err.Error())
|
||||
}
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
@@ -364,7 +286,7 @@ Typically run during initrd to unlock all the LUKS partitions found
|
||||
&cli.StringFlag{},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
return unlockAll()
|
||||
return lib.UnlockAll()
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -28,7 +28,7 @@ type Bus struct {
|
||||
|
||||
func (b *Bus) LoadProviders() {
|
||||
wd, _ := os.Getwd()
|
||||
b.Manager.Autoload("kcrypt-discovery", "/system/discovery", "/oem/kcrypt", "/oem/system/discovery", wd).Register()
|
||||
b.Manager.Autoload("kcrypt-discovery", "/sysroot/system/discovery", "/system/discovery", "/oem/kcrypt", "/oem/system/discovery", wd).Register()
|
||||
}
|
||||
|
||||
func (b *Bus) Initialize() {
|
||||
|
||||
143
pkg/config/config.go
Normal file
143
pkg/config/config.go
Normal file
@@ -0,0 +1,143 @@
|
||||
// package config contains all the logic around kcrypt config
|
||||
// This config includes everything below `kcrypt:` in the kairos config yaml
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kairos/pkg/config/collector"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v1"
|
||||
)
|
||||
|
||||
// There are the directories under which we expect to find kairos configuration.
|
||||
// When we are booted from an iso (during installation), configuration is expected
|
||||
// under `/oem`. When we are booting an installed system (in initramfs phase),
|
||||
// the path is `/sysroot/oem`.
|
||||
var ConfigScanDirs = []string{"/oem", "/sysroot/oem"}
|
||||
|
||||
// This file is "hardcoded" to `/oem` because we only use this at install time
|
||||
// in which case the config is in `/oem`.
|
||||
var MappingsFile = "/oem/91-kcrypt-mappings.yaml"
|
||||
|
||||
type Config struct {
|
||||
Kcrypt struct {
|
||||
UUIDLabelMappings map[string]string `yaml:"uuid_label_mappings,omitempty"`
|
||||
}
|
||||
}
|
||||
|
||||
func PartitionToString(p *block.Partition) string {
|
||||
return fmt.Sprintf("%s:%s:%s", p.FilesystemLabel, p.Name, p.UUID)
|
||||
}
|
||||
|
||||
// Takes a partition info string (as returned by PartitionToString) and return
|
||||
// the partition label and the UUID
|
||||
func partitionDataFromString(partitionStr string) (string, string, error) {
|
||||
parts := strings.Split(partitionStr, ":")
|
||||
if len(parts) != 3 {
|
||||
return "", "", errors.New("partition string not valid")
|
||||
}
|
||||
|
||||
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[2]), nil
|
||||
}
|
||||
|
||||
func GetConfiguration(configDirs []string) (Config, error) {
|
||||
var result Config
|
||||
|
||||
o := &collector.Options{}
|
||||
|
||||
if err := o.Apply(collector.Directories(configDirs...), collector.NoLogs); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
c, err := collector.Scan(o)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
configStr, err := c.String()
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if err = yaml.Unmarshal([]byte(configStr), &result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SetMapping updates the Config with partition information for
|
||||
// one partition. This doesn't persist on the file. WriteMappings needs to
|
||||
// be called after all mapping are in the Config (possibly with multiple calls
|
||||
// to this function).
|
||||
func (c *Config) SetMapping(partitionInfo string) error {
|
||||
label, uuid, err := partitionDataFromString(partitionInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Initialize map
|
||||
if c.Kcrypt.UUIDLabelMappings == nil {
|
||||
c.Kcrypt.UUIDLabelMappings = map[string]string{}
|
||||
}
|
||||
c.Kcrypt.UUIDLabelMappings[label] = uuid
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMappings will create or replace the MappingsFile
|
||||
// It's called by kairos agent, at installation time, after the partitions
|
||||
// have been created (and we have the UUIDs available).
|
||||
func (c *Config) WriteMappings(fileName string) error {
|
||||
data, err := yaml.Marshal(&c)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshalling the kcrypt configuration to yaml")
|
||||
}
|
||||
|
||||
data = append([]byte(collector.DefaultHeader+"\n"), data...)
|
||||
|
||||
err = os.WriteFile(fileName, data, 0744)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "writing the kcrypt configuration file")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Config) LookupUUIDForLabel(l string) string {
|
||||
return c.Kcrypt.UUIDLabelMappings[l]
|
||||
}
|
||||
|
||||
func (c Config) LookupLabelForUUID(uuid string) string {
|
||||
for k, v := range c.Kcrypt.UUIDLabelMappings {
|
||||
if v == uuid {
|
||||
return k
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetLabelForUUID returns the partition label for a known UUID
|
||||
// UUIDS are generated on luksify method
|
||||
// They are generated by setting the namespace to DNS and the name to the fs label, so they are always the same
|
||||
func (c Config) GetLabelForUUID(uuidCheck string) (string, error) {
|
||||
persistent := uuid.NewV5(uuid.NamespaceURL, "COS_PERSISTENT")
|
||||
oem := uuid.NewV5(uuid.NamespaceURL, "COS_OEM")
|
||||
fmt.Printf("Checking uuid: %s\n", uuidCheck)
|
||||
parsedUUID, err := uuid.FromString(uuidCheck)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch parsedUUID {
|
||||
case persistent:
|
||||
return "COS_PERSISTENT", nil
|
||||
case oem:
|
||||
return "COS_OEM", nil
|
||||
default:
|
||||
return "", errors.New("no partition found with that uuid")
|
||||
|
||||
}
|
||||
}
|
||||
216
pkg/config/config_test.go
Normal file
216
pkg/config/config_test.go
Normal file
@@ -0,0 +1,216 @@
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/kairos-io/kairos/pkg/config/collector"
|
||||
configpkg "github.com/kairos-io/kcrypt/pkg/config"
|
||||
)
|
||||
|
||||
var _ = Describe("Config", func() {
|
||||
var tmpDir string
|
||||
var err error
|
||||
|
||||
BeforeEach(func() {
|
||||
tmpDir, err = os.MkdirTemp("", "kcrypt-configuration-*")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
os.RemoveAll(tmpDir)
|
||||
})
|
||||
|
||||
Describe("GetConfiguration", func() {
|
||||
When("the no relevant block exists", func() {
|
||||
It("returns empty Config", func() {
|
||||
c, err := configpkg.GetConfiguration([]string{tmpDir})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(c.Kcrypt.UUIDLabelMappings).To(BeEmpty())
|
||||
})
|
||||
})
|
||||
|
||||
When("a kcrypt block exists", func() {
|
||||
var tmpFile *os.File
|
||||
|
||||
BeforeEach(func() {
|
||||
tmpFile, err = os.CreateTemp(tmpDir, "config-*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
data := []byte(`#cloud-config
|
||||
kcrypt:
|
||||
uuid_label_mappings:
|
||||
COS_PERSISTENT: some_uuid_here
|
||||
`)
|
||||
err := os.WriteFile(tmpFile.Name(), data, 0744)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("returns the Config", func() {
|
||||
c, err := configpkg.GetConfiguration([]string{tmpDir})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(c.Kcrypt.UUIDLabelMappings["COS_PERSISTENT"]).To(Equal("some_uuid_here"))
|
||||
})
|
||||
})
|
||||
|
||||
When("multiple kcrypt block exist", func() {
|
||||
var tmpFile1, tmpFile2 *os.File
|
||||
|
||||
BeforeEach(func() {
|
||||
tmpFile1, err = os.CreateTemp(tmpDir, "config-*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
data := []byte(`#cloud-config
|
||||
kcrypt:
|
||||
challenger_server: http://test.org:8082
|
||||
`)
|
||||
err := os.WriteFile(tmpFile1.Name(), data, 0744)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
tmpFile2, err = os.CreateTemp(tmpDir, "config-*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
data = []byte(`#cloud-config
|
||||
kcrypt:
|
||||
uuid_label_mappings:
|
||||
COS_PERSISTENT: some_uuid_here
|
||||
`)
|
||||
err = os.WriteFile(tmpFile2.Name(), data, 0744)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("returns the merged Config", func() {
|
||||
c, err := configpkg.GetConfiguration([]string{tmpDir})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(c.Kcrypt.UUIDLabelMappings["COS_PERSISTENT"]).To(Equal("some_uuid_here"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("SetMapping", func() {
|
||||
var c configpkg.Config
|
||||
|
||||
BeforeEach(func() {
|
||||
c, err = configpkg.GetConfiguration([]string{tmpDir})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("adds partition information when empty and appends when not", func() {
|
||||
Expect(c.Kcrypt.UUIDLabelMappings).To(BeNil())
|
||||
err := c.SetMapping("some_label:some_name:some_uuid")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(c.Kcrypt.UUIDLabelMappings["some_label"]).To(Equal("some_uuid"))
|
||||
|
||||
err = c.SetMapping("some_other_label:some_name:some_other_uuid")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(c.Kcrypt.UUIDLabelMappings["some_label"]).To(Equal("some_uuid"))
|
||||
Expect(c.Kcrypt.UUIDLabelMappings["some_other_label"]).To(Equal("some_other_uuid"))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("WriteMappings", func() {
|
||||
var tmpFile *os.File
|
||||
var c configpkg.Config
|
||||
|
||||
When("mappings config file already exists", func() {
|
||||
BeforeEach(func() {
|
||||
tmpFile, err = os.CreateTemp(tmpDir, "config-*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
data := []byte(`kcrypt:
|
||||
uuid_label_mappings:
|
||||
COS_PERSISTENT: some_uuid_here
|
||||
`)
|
||||
err := os.WriteFile(tmpFile.Name(), data, 0744)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("replaces the file contents", func() {
|
||||
err := c.SetMapping("COS_PERSISTENT:the_new_name:the_new_uuid")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = c.WriteMappings(tmpFile.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
data, err := os.ReadFile(tmpFile.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(collector.HasValidHeader(string(data))).To(BeTrue())
|
||||
|
||||
newConfig, err := configpkg.GetConfiguration([]string{tmpDir})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(newConfig.Kcrypt.UUIDLabelMappings["COS_PERSISTENT"]).To(Equal("the_new_uuid"))
|
||||
})
|
||||
})
|
||||
|
||||
When("a mappings configuration file doesn't exist", func() {
|
||||
BeforeEach(func() {
|
||||
tmpFile, err = os.CreateTemp(tmpDir, "config-*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// We will reuse the same name but we make sure the file doesn't exist.
|
||||
os.RemoveAll(tmpFile.Name())
|
||||
})
|
||||
|
||||
It("creates the file with the given mappings", func() {
|
||||
err := c.SetMapping("COS_PERSISTENT:the_new_name:the_new_uuid")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = c.WriteMappings(tmpFile.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
newConfig, err := configpkg.GetConfiguration([]string{tmpDir})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(newConfig.Kcrypt.UUIDLabelMappings["COS_PERSISTENT"]).To(Equal("the_new_uuid"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("LookupUUIDForLabel", func() {
|
||||
var tmpFile *os.File
|
||||
var c configpkg.Config
|
||||
|
||||
BeforeEach(func() {
|
||||
tmpFile, err = os.CreateTemp(tmpDir, "config-*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Should trim the whitespace
|
||||
err = c.SetMapping("COS_PERSISTENT:the_new_name:some_uuid_1\n")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = c.WriteMappings(tmpFile.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("returns the correct UUID", func() {
|
||||
uuid := c.LookupUUIDForLabel("COS_PERSISTENT")
|
||||
Expect(uuid).To(Equal("some_uuid_1"))
|
||||
})
|
||||
|
||||
It("returns an empty UUID when the label is not found", func() {
|
||||
uuid := c.LookupUUIDForLabel("DOESNT_EXIST")
|
||||
Expect(uuid).To(Equal(""))
|
||||
})
|
||||
|
||||
It("returns an empty UUID when the UUIDLabelMappings is nil", func() {
|
||||
c.Kcrypt.UUIDLabelMappings = nil
|
||||
uuid := c.LookupUUIDForLabel("COS_PERSISTENT")
|
||||
Expect(uuid).To(Equal(""))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("LookupLabelForUUID", func() {
|
||||
var tmpFile *os.File
|
||||
var c configpkg.Config
|
||||
|
||||
BeforeEach(func() {
|
||||
tmpFile, err = os.CreateTemp(tmpDir, "config-*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = c.SetMapping("COS_PERSISTENT:the_new_name:some_uuid_1")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = c.WriteMappings(tmpFile.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("returns the correct label", func() {
|
||||
uuid := c.LookupLabelForUUID("some_uuid_1")
|
||||
Expect(uuid).To(Equal("COS_PERSISTENT"))
|
||||
})
|
||||
|
||||
It("returns an empty label when UUID doesn't exist", func() {
|
||||
uuid := c.LookupLabelForUUID("doesnt_exist")
|
||||
Expect(uuid).To(Equal(""))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
package partition_info
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -9,5 +9,5 @@ import (
|
||||
|
||||
func TestPartitionINfo(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "PartitionInfo file parser test suite")
|
||||
RunSpecs(t, "Kcrypt config test suite")
|
||||
}
|
||||
115
pkg/lib/unlock.go
Normal file
115
pkg/lib/unlock.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/anatol/luks.go"
|
||||
"github.com/jaypipes/ghw"
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kairos-sdk/utils"
|
||||
"github.com/kairos-io/kcrypt/pkg/bus"
|
||||
configpkg "github.com/kairos-io/kcrypt/pkg/config"
|
||||
"github.com/mudler/go-pluggable"
|
||||
)
|
||||
|
||||
// UnlockAll Unlocks all encrypted devices found in the system
|
||||
func UnlockAll() error {
|
||||
bus.Manager.Initialize()
|
||||
|
||||
config, err := configpkg.GetConfiguration(configpkg.ConfigScanDirs)
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: Could not read kcrypt configuration '%s'\n", err.Error())
|
||||
}
|
||||
|
||||
blk, err := ghw.Block()
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: Error reading partitions '%s \n", err.Error())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, disk := range blk.Disks {
|
||||
for _, p := range disk.Partitions {
|
||||
if p.Type == "crypto_LUKS" {
|
||||
// Get the luks UUID directly from cryptsetup
|
||||
volumeUUID, err := utils.SH(fmt.Sprintf("cryptsetup luksUUID %s", filepath.Join("/dev", p.Name)))
|
||||
fmt.Printf("Got luks UUID %s for partition %s\n", volumeUUID, p.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
volumeUUID = strings.TrimSpace(volumeUUID)
|
||||
if volumeUUID == "" {
|
||||
fmt.Printf("No uuid for %s, skipping\n", p.Name)
|
||||
continue
|
||||
}
|
||||
p.FilesystemLabel, err = config.GetLabelForUUID(volumeUUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Check if device is already mounted
|
||||
// We mount it under /dev/mapper/DEVICE, so It's pretty easy to check
|
||||
if !utils.Exists(filepath.Join("/dev", "mapper", p.Name)) {
|
||||
fmt.Printf("Unmounted Luks found at '%s' LABEL '%s' \n", filepath.Join("/dev", p.Name), p.FilesystemLabel)
|
||||
err = UnlockDisk(p)
|
||||
if err != nil {
|
||||
fmt.Printf("Unlocking failed: '%s'\n", err.Error())
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Device %s seems to be mounted at %s, skipping\n", filepath.Join("/dev", p.Name), filepath.Join("/dev", "mapper", p.Name))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnlockDisk unlocks a single block.Partition
|
||||
func UnlockDisk(b *block.Partition) error {
|
||||
pass, err := GetPassword(b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retreiving password remotely: %w", err)
|
||||
}
|
||||
|
||||
return LuksUnlock(filepath.Join("/dev", b.Name), b.Name, pass)
|
||||
}
|
||||
|
||||
// GetPassword gets the password for a block.Partition
|
||||
// TODO: Ask to discovery a pass to unlock. keep waiting until we get it and a timeout is exhausted with retrials (exp backoff)
|
||||
func GetPassword(b *block.Partition) (password string, err error) {
|
||||
bus.Reload()
|
||||
|
||||
bus.Manager.Response(bus.EventDiscoveryPassword, func(p *pluggable.Plugin, r *pluggable.EventResponse) {
|
||||
password = r.Data
|
||||
if r.Errored() {
|
||||
err = fmt.Errorf("failed discovery: %s", r.Error)
|
||||
}
|
||||
})
|
||||
_, err = bus.Manager.Publish(bus.EventDiscoveryPassword, b)
|
||||
if err != nil {
|
||||
return password, err
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
return password, fmt.Errorf("received empty password")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func LuksUnlock(device, mapper, password string) error {
|
||||
dev, err := luks.Open(device)
|
||||
if err != nil {
|
||||
// handle error
|
||||
return err
|
||||
}
|
||||
defer dev.Close()
|
||||
|
||||
err = dev.Unlock(0, []byte(password), mapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
package partition_info
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const DefaultPartitionInfoFile = "/oem/partition_info.yaml"
|
||||
|
||||
// PartitionInfo maps a partition label to a partition UUID.
|
||||
// It's used in order to be able to ask the kcrypt-challenger for the passphrase
|
||||
// using the partition label, even when the label is not accessible (e.g. before
|
||||
// decrypting the partition). The UUID can be used to lookup the partition label
|
||||
// and make the request.
|
||||
type PartitionInfo struct {
|
||||
file string
|
||||
mapping map[string]string
|
||||
}
|
||||
|
||||
// NewPartitionInfoFromFile reads the given partition info file (if one exists)
|
||||
// and returns a pointer to a PartitionInfo object.
|
||||
// If a file doesn't exist, the function will create one and return an "empty"
|
||||
// PartitionInfo object.
|
||||
// The boolean return value indicates whether a file existed or not (true means,
|
||||
// a file existed already).
|
||||
func NewPartitionInfoFromFile(file string) (*PartitionInfo, bool, error) {
|
||||
existed, err := createInfoFileIfNotExists(file)
|
||||
if err != nil {
|
||||
return nil, existed, err
|
||||
}
|
||||
|
||||
mapping, err := ParsePartitionInfoFile(file)
|
||||
if err != nil {
|
||||
return nil, existed, err
|
||||
}
|
||||
|
||||
return &PartitionInfo{
|
||||
file: file,
|
||||
mapping: mapping,
|
||||
}, existed, nil
|
||||
}
|
||||
|
||||
func (pi PartitionInfo) LookupUUIDForLabel(l string) string {
|
||||
return pi.mapping[l]
|
||||
}
|
||||
|
||||
func (pi PartitionInfo) LookupLabelForUUID(uuid string) string {
|
||||
for k, v := range pi.mapping {
|
||||
if v == uuid {
|
||||
return k
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// UpdatePartitionLabelMapping takes partition information as a string argument
|
||||
// the the form: `label:name:uuid` (that's what the `kcrypt encrypt` command returns
|
||||
// on success. This function stores it in the PartitionInfoFile yaml file for
|
||||
// later use.
|
||||
func (pi PartitionInfo) UpdateMapping(partitionData string) error {
|
||||
label, uuid := PartitionDataFromString(partitionData)
|
||||
pi.mapping[label] = uuid
|
||||
|
||||
return pi.save()
|
||||
}
|
||||
|
||||
func (pi PartitionInfo) IsMappingNil() bool {
|
||||
return pi.mapping == nil
|
||||
}
|
||||
|
||||
func (pi PartitionInfo) save() error {
|
||||
data, err := yaml.Marshal(&pi.mapping)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshalling the new partition info to yaml")
|
||||
}
|
||||
err = ioutil.WriteFile(pi.file, data, 0)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "writing back the partition info file")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func PartitionToString(p *block.Partition) string {
|
||||
return fmt.Sprintf("%s:%s:%s", p.Label, p.Name, p.UUID)
|
||||
}
|
||||
|
||||
// Takes a partition info string (as returned by PartitionToString) and return
|
||||
// the partition label and the UUID
|
||||
func PartitionDataFromString(partitionStr string) (string, string) {
|
||||
parts := strings.Split(partitionStr, ":")
|
||||
|
||||
return parts[0], parts[2]
|
||||
}
|
||||
|
||||
func ParsePartitionInfoFile(file string) (map[string]string, error) {
|
||||
var result map[string]string
|
||||
|
||||
yamlFile, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return result, errors.Wrap(err, "reading the partition info file")
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(yamlFile, &result)
|
||||
if err != nil {
|
||||
return result, errors.Wrap(err, "unmarshalling partition info file")
|
||||
}
|
||||
if result == nil {
|
||||
result = map[string]string{}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// createInfoFileIfNotExists returns true if file already exists or creates the
|
||||
// the file if it doesn't exist and returns false.
|
||||
func createInfoFileIfNotExists(fileName string) (bool, error) {
|
||||
_, err := os.Stat(fileName)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
if _, err := os.Create(fileName); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
package partition_info_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
pi "github.com/kairos-io/kcrypt/pkg/partition_info"
|
||||
)
|
||||
|
||||
var _ = Describe("Partition Info file parsing", func() {
|
||||
Describe("NewPartitionInfoFromFile", func() {
|
||||
var file string
|
||||
|
||||
BeforeEach(func() {
|
||||
file = "../../tests/assets/partition_info.yaml"
|
||||
})
|
||||
When("the files exists already", func() {
|
||||
It("returns 'true' and a PartitionInfo object", func() {
|
||||
result, existed, err := pi.NewPartitionInfoFromFile(file)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(result).ToNot(BeNil())
|
||||
Expect(existed).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
When("a file doesn't exist", func() {
|
||||
var fileName string
|
||||
BeforeEach(func() {
|
||||
fileName = path.Join(
|
||||
os.TempDir(),
|
||||
fmt.Sprintf("partition-info-%d.yaml", time.Now().UnixNano()))
|
||||
})
|
||||
|
||||
It("creates the file and returns 'false' and a non nil mapping", func() {
|
||||
result, existed, err := pi.NewPartitionInfoFromFile(fileName)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(result).ToNot(BeNil())
|
||||
Expect(existed).To(BeFalse())
|
||||
_, err = os.Stat(fileName)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(result).ToNot(BeNil())
|
||||
Expect(result.IsMappingNil()).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("ParsePartitionInfoFile", func() {
|
||||
var file string
|
||||
|
||||
BeforeEach(func() {
|
||||
file = "../../tests/assets/partition_info.yaml"
|
||||
})
|
||||
|
||||
It("parses the file correctly", func() {
|
||||
info, err := pi.ParsePartitionInfoFile(file)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(info)).To(Equal(2))
|
||||
Expect(info["COS_PERSISTENT"]).To(Equal("some_uuid_1"))
|
||||
Expect(info["COS_OTHER"]).To(Equal("some_uuid_2"))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("PartitionToString", func() {
|
||||
var partition *block.Partition
|
||||
|
||||
BeforeEach(func() {
|
||||
partition = &block.Partition{
|
||||
Disk: nil,
|
||||
Name: "sda1",
|
||||
Label: "COS_PERSISTENT",
|
||||
MountPoint: "/mnt/sda1",
|
||||
UUID: "some_uuid_here",
|
||||
}
|
||||
})
|
||||
|
||||
It("returns a string representation of the partition data", func() {
|
||||
Expect(pi.PartitionToString(partition)).To(Equal("COS_PERSISTENT:sda1:some_uuid_here"))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("PartitionDataFromString", func() {
|
||||
var partitionData string
|
||||
|
||||
BeforeEach(func() {
|
||||
partitionData = "THE_LABEL:the_name:the_uuid"
|
||||
})
|
||||
|
||||
It("returns the label and the uuid", func() {
|
||||
label, uuid := pi.PartitionDataFromString(partitionData)
|
||||
Expect(label).To(Equal("THE_LABEL"))
|
||||
Expect(uuid).To(Equal("the_uuid"))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("UpdateMapping", func() {
|
||||
var file *os.File
|
||||
var err error
|
||||
var partitionInfo *pi.PartitionInfo
|
||||
|
||||
BeforeEach(func() {
|
||||
file, err = ioutil.TempFile("", "partition-info.*.yaml")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = file.Write([]byte("TO_KEEP: old_uuid_1"))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
partitionInfo, _, err = pi.NewPartitionInfoFromFile(file.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
os.Remove(file.Name())
|
||||
})
|
||||
|
||||
It("Updates the file correctly from a `kcrypt encrypt` return value", func() {
|
||||
partitionData := "TO_BE_ADDED:some_name:new_uuid"
|
||||
|
||||
err = partitionInfo.UpdateMapping(partitionData)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
dat, err := os.ReadFile(file.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
expectedContent := `TO_BE_ADDED: new_uuid
|
||||
TO_KEEP: old_uuid_1
|
||||
`
|
||||
Expect(string(dat)).To(Equal(expectedContent))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("LookupUUIDForLabel", func() {
|
||||
var file string
|
||||
var partitionInfo *pi.PartitionInfo
|
||||
var err error
|
||||
|
||||
BeforeEach(func() {
|
||||
file = "../../tests/assets/partition_info.yaml"
|
||||
partitionInfo, _, err = pi.NewPartitionInfoFromFile(file)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("returns the correct UUID", func() {
|
||||
uuid := partitionInfo.LookupUUIDForLabel("COS_PERSISTENT")
|
||||
Expect(uuid).To(Equal("some_uuid_1"))
|
||||
})
|
||||
|
||||
It("returns an empty UUID when the label is not found", func() {
|
||||
uuid := partitionInfo.LookupUUIDForLabel("DOESNT_EXIST")
|
||||
Expect(uuid).To(Equal(""))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("LookupLabelForUUID", func() {
|
||||
var file string
|
||||
var partitionInfo *pi.PartitionInfo
|
||||
var err error
|
||||
|
||||
BeforeEach(func() {
|
||||
file = "../../tests/assets/partition_info.yaml"
|
||||
partitionInfo, _, err = pi.NewPartitionInfoFromFile(file)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("returns the correct label", func() {
|
||||
uuid := partitionInfo.LookupLabelForUUID("some_uuid_1")
|
||||
Expect(uuid).To(Equal("COS_PERSISTENT"))
|
||||
})
|
||||
|
||||
It("returns an empty label when UUID doesn't exist", func() {
|
||||
uuid := partitionInfo.LookupLabelForUUID("doesnt_exist")
|
||||
Expect(uuid).To(Equal(""))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,2 +0,0 @@
|
||||
COS_PERSISTENT: some_uuid_1
|
||||
COS_OTHER: some_uuid_2
|
||||
Reference in New Issue
Block a user