diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 9790a6af..478f5fab 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -10,6 +10,10 @@ jobs: create-release: name: Create Release runs-on: ubuntu-latest + strategy: + matrix: + go_version: [ 'stable' ] + node_version: [ '20' ] outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: @@ -18,16 +22,17 @@ jobs: - uses: actions/cache@v4 with: path: | - ~/.cache/go-build + ~/.npm + ~/.cache ~/go/pkg/mod - /usr/local/share/.cache/yarn - key: ${{ runner.os }}-koko - restore-keys: ${{ runner.os }}-koko + key: ${{ runner.os }}-build-${{ github.sha }} + restore-keys: ${{ runner.os }}-build- - name: Get version + id: get_version run: | TAG=$(basename ${GITHUB_REF}) - echo "TAG=$TAG" >> $GITHUB_ENV + echo "TAG=$TAG" >> $GITHUB_OUTPUT - name: Create Release id: create_release @@ -36,23 +41,24 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: config-name: release-config.yml - version: ${{ env.TAG }} - tag: ${{ env.TAG }} + version: ${{ steps.get_version.outputs.TAG }} + tag: ${{ steps.get_version.outputs.TAG }} - uses: actions/setup-node@v4 with: - node-version: '20.15' + node-version: ${{ matrix.node_version }} - uses: actions/setup-go@v5 with: - go-version: '1.22' # The Go version to download (if necessary) and use. + go-version: ${{ matrix.go_version }} + cache: false - name: Make Build id: make_build run: | make all -s && ls build env: - VERSION: ${{ env.TAG }} + VERSION: ${{ steps.get_version.outputs.TAG }} - name: Release Upload Assets uses: softprops/action-gh-release@v2 diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 8611b593..4478309f 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -8,9 +8,6 @@ before: - go mod tidy - go generate ./... -snapshot: - version_template: "{{ .Tag }}-next" - builds: - id: koko main: ./cmd/koko/ @@ -87,6 +84,7 @@ archives: - LICENSE - README.md - config_example.yml + - entrypoint.sh - locale/* - src: utils/init-kubectl.sh dst: init-kubectl @@ -98,7 +96,7 @@ archives: name_template: "{{ .ProjectName }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }}" checksum: - name_template: "{{ .ProjectName }}_checksums.txt" + name_template: "checksums.txt" release: draft: true diff --git a/Dockerfile b/Dockerfile index 42b8722b..92ef9470 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM jumpserver/koko-base:20241030_063234 AS stage-build +FROM jumpserver/koko-base:20241217_053647 AS stage-build WORKDIR /opt/koko ARG TARGETARCH @@ -31,18 +31,15 @@ ENV LANG=en_US.UTF-8 ARG DEPENDENCIES=" \ ca-certificates" -ARG APT_MIRROR=http://mirrors.ustc.edu.cn +ARG APT_MIRROR=http://deb.debian.org + RUN set -ex \ - && rm -f /etc/apt/apt.conf.d/docker-clean \ - && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \ && sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && apt-get update \ && apt-get install -y --no-install-recommends ${DEPENDENCIES} \ && apt-get clean all \ - && echo "no" | dpkg-reconfigure dash \ - && sed -i "s@# export @export @g" ~/.bashrc \ - && sed -i "s@# alias @alias @g" ~/.bashrc + && rm -rf /var/lib/apt/lists/* WORKDIR /opt/koko diff --git a/Dockerfile-base b/Dockerfile-base index 9eff8c5c..9050f714 100644 --- a/Dockerfile-base +++ b/Dockerfile-base @@ -1,5 +1,5 @@ FROM redis:6.2-bullseye AS redis-stage -FROM golang:1.22-bullseye AS stage-go-build +FROM golang:1.23-bullseye AS stage-go-build FROM node:20.15-bullseye COPY --from=stage-go-build /usr/local/go/ /usr/local/go/ @@ -10,18 +10,17 @@ ENV PATH=/go/bin:/usr/local/go/bin:$PATH ARG TARGETARCH ARG NPM_REGISTRY="https://registry.npmmirror.com" ENV NPM_REGISTY=$NPM_REGISTRY -RUN set -ex \ - && echo "no" | dpkg-reconfigure dash + RUN set -ex \ && npm config set registry ${NPM_REGISTRY} \ && yarn config set registry ${NPM_REGISTRY} WORKDIR /opt -ARG HELM_VERSION=v3.14.3 -ARG KUBECTL_VERSION=v1.29.3 -ARG CHECK_VERSION=v1.0.3 -ARG USQL_VERSION=v0.0.4 +ARG HELM_VERSION=v3.16.1 +ARG KUBECTL_VERSION=v1.31.3 +ARG CHECK_VERSION=v1.0.4 +ARG USQL_VERSION=v0.0.5 RUN set -ex \ && mkdir -p /opt/koko/bin \ @@ -32,7 +31,7 @@ RUN set -ex \ && tar -xf helm-${HELM_VERSION}-linux-${TARGETARCH}.tar.gz --strip-components=1 -C /opt/koko/bin/ linux-${TARGETARCH}/helm \ && mv /opt/koko/bin/helm /opt/koko/bin/rawhelm \ && wget https://github.com/jumpserver-dev/healthcheck/releases/download/${CHECK_VERSION}/check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz \ - && tar -xf check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz -C /opt/koko/bin/ \ + && tar -xf check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz -C /opt/koko/bin/ check \ && wget https://github.com/jumpserver-dev/usql/releases/download/${USQL_VERSION}/usql-${USQL_VERSION}-linux-${TARGETARCH}.tar.gz \ && tar -xf usql-${USQL_VERSION}-linux-${TARGETARCH}.tar.gz -C /opt/koko/bin/ \ && wget -O /opt/koko/.kubectl_aliases https://github.com/ahmetb/kubectl-aliases/raw/master/.kubectl_aliases \ @@ -40,11 +39,9 @@ RUN set -ex \ && chown root:root /opt/koko/bin/* \ && rm -f *.tar.gz - - WORKDIR /opt/koko -ARG MONGOSH_VERSION=2.3.2 +ARG MONGOSH_VERSION=2.3.4 RUN set -ex \ && mkdir -p /opt/koko/lib \ && \ diff --git a/Makefile b/Makefile index e53f71b7..fac4be3f 100644 --- a/Makefile +++ b/Makefile @@ -35,13 +35,15 @@ define make_artifact_full GOOS=$(1) GOARCH=$(2) $(K8SCMDBUILD) -o $(BUILDDIR)/kubectl-$(1)-$(2) $(KUBECTLFILE) GOOS=$(1) GOARCH=$(2) $(K8SCMDBUILD) -o $(BUILDDIR)/helm-$(1)-$(2) $(HELMFILE) mkdir -p $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/locale/ - cp $(BUILDDIR)/$(NAME)-$(1)-$(2) $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/$(NAME) - cp $(BUILDDIR)/kubectl-$(1)-$(2) $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/kubectl cp $(BUILDDIR)/helm-$(1)-$(2) $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/helm - cp -r $(BASEPATH)/locale/* $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/locale/ - cp -r $(BASEPATH)/config_example.yml $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/config_example.yml - cp -r $(BASEPATH)/utils/init-kubectl.sh $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/init-kubectl.sh + cp $(BUILDDIR)/kubectl-$(1)-$(2) $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/kubectl + cp README.md $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/README.md + cp LICENSE $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/LICENSE + cp config_example.yml $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/config_example.yml + cp entrypoint.sh $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/entrypoint.sh + cp utils/init-kubectl.sh $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/init-kubectl.sh + cp -r locale/* $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2)/locale/ cd $(BUILDDIR) && tar -czvf $(NAME)-$(VERSION)-$(1)-$(2).tar.gz $(NAME)-$(VERSION)-$(1)-$(2) rm -rf $(BUILDDIR)/$(NAME)-$(VERSION)-$(1)-$(2) $(BUILDDIR)/$(NAME)-$(1)-$(2) $(BUILDDIR)/kubectl-$(1)-$(2) $(BUILDDIR)/helm-$(1)-$(2) @@ -61,6 +63,7 @@ all: koko-ui $(call make_artifact_full,linux,ppc64le) $(call make_artifact_full,linux,s390x) $(call make_artifact_full,linux,riscv64) + $(call make_artifact_full,linux,loong64) local: koko-ui $(call make_artifact_full,$(shell go env GOOS),$(shell go env GOARCH)) diff --git a/locale/en_US/LC_MESSAGES/koko.po b/locale/en_US/LC_MESSAGES/koko.po index 6d6c0fc1..40679cac 100644 --- a/locale/en_US/LC_MESSAGES/koko.po +++ b/locale/en_US/LC_MESSAGES/koko.po @@ -90,8 +90,20 @@ msgid "ACL reject" msgstr "" #. lang.T +#: pkg/handler/asset.go:223 +msgid "" +"Face ACL is not supported yet. Please use the WebTerminal to connect the " +"asset." +msgstr "" + +#. lang.T +#. lang.T +#: pkg/handler/asset.go:238 pkg/handler/asset.go:247 +msgid "Unknown error code: %s, detail: %s" +msgstr "" + #. lang.T -#: pkg/handler/asset.go:231 pkg/handler/asset.go:248 +#: pkg/handler/asset.go:258 msgid "get connect token err" msgstr "" @@ -226,10 +238,17 @@ msgstr "" #. lang.T #. lang.T #. lang.T +#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 +#: pkg/handler/direct_handler.go:445 +msgid "" +"Face verification is not supported yet. Please use the WebTerminal to " +"connect the asset." +msgstr "" + #. lang.T #. lang.T -#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 -#: pkg/handler/direct_handler.go:453 pkg/handler/direct_handler.go:469 +#. lang.T +#: pkg/handler/direct_handler.go:460 pkg/handler/direct_handler.go:476 #: pkg/handler/dispatch.go:139 msgid "Node: [ ID.Name(Asset amount) ]" msgstr "" @@ -383,14 +402,14 @@ msgid "" msgstr "" #. lang.T -#: pkg/proxy/parser.go:282 +#: pkg/proxy/parser.go:283 msgid "The command '%s' requires review. Continue or not [Y/n]?" msgstr "" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:302 pkg/proxy/parser.go:309 pkg/proxy/parser.go:463 +#: pkg/proxy/parser.go:303 pkg/proxy/parser.go:310 pkg/proxy/parser.go:463 msgid "Command `%s` is forbidden" msgstr "" @@ -400,14 +419,14 @@ msgid "have no permission to download file" msgstr "" #. lang.T -#: pkg/proxy/parser.go:608 +#: pkg/proxy/parser.go:606 msgid "" "Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C " "or CTRL+D." msgstr "" #. lang.T -#: pkg/proxy/parser.go:618 +#: pkg/proxy/parser.go:616 msgid "" "Need ticket confirm to execute command, already send email to the reviewers" msgstr "" @@ -416,7 +435,7 @@ msgstr "" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:619 pkg/proxy/parser.go:620 pkg/proxy/server.go:58 +#: pkg/proxy/parser.go:617 pkg/proxy/parser.go:618 pkg/proxy/server.go:58 #: pkg/proxy/server.go:62 msgid "" "HandleTask does not support protocol %s, please use web terminal to access" @@ -428,45 +447,45 @@ msgid "Account <%s> and asset <%s> protocol are inconsistent." msgstr "" #. lang.T -#: pkg/proxy/server.go:101 +#: pkg/proxy/server.go:102 msgid "You don't have permission login %s" msgstr "" #. lang.T -#: pkg/proxy/server.go:337 +#: pkg/proxy/server.go:334 msgid "You get auth token failed" msgstr "" #. lang.T -#: pkg/proxy/server.go:348 +#: pkg/proxy/server.go:345 msgid "Get auth password failed" msgstr "" #. lang.T #. lang.T -#: pkg/proxy/server.go:364 pkg/proxy/server.go:421 +#: pkg/proxy/server.go:361 pkg/proxy/server.go:418 msgid "Reuse SSH connections (%s@%s) [Number of connections: %d]" msgstr "" #. lang.T -#: pkg/proxy/server.go:677 +#: pkg/proxy/server.go:674 msgid "Switched to %s" msgstr "" #. lang.T #. lang.T -#: pkg/proxy/server.go:774 pkg/proxy/server.go:919 +#: pkg/proxy/server.go:771 pkg/proxy/server.go:916 msgid "Connect with api server failed" msgstr "" #. lang.T -#: pkg/proxy/server.go:968 +#: pkg/proxy/server.go:977 msgid "Start domain gateway failed %s" msgstr "" #. lang.T #. lang.T -#: pkg/proxy/server.go:976 pkg/proxy/server_options.go:108 +#: pkg/proxy/server.go:985 pkg/proxy/server_options.go:108 msgid "Manual" msgstr "" @@ -496,18 +515,18 @@ msgid "Connecting to Kubernetes %s container %s" msgstr "" #. lang.T -#: pkg/proxy/switch.go:325 +#: pkg/proxy/switch.go:328 msgid "Session max time reached, disconnect" msgstr "" #. lang.T #. lang.T -#: pkg/proxy/switch.go:336 pkg/proxy/switch.go:345 +#: pkg/proxy/switch.go:337 pkg/proxy/switch.go:344 msgid "Permission has expired, disconnect" msgstr "" #. lang.T -#: pkg/proxy/switch.go:357 +#: pkg/proxy/switch.go:354 msgid "Terminated by admin %s" msgstr "" diff --git a/locale/ja_JP/LC_MESSAGES/koko.po b/locale/ja_JP/LC_MESSAGES/koko.po index b70addd4..f0af95da 100644 --- a/locale/ja_JP/LC_MESSAGES/koko.po +++ b/locale/ja_JP/LC_MESSAGES/koko.po @@ -96,8 +96,23 @@ msgid "ACL reject" msgstr "は拒否されました" #. lang.T +#: pkg/handler/asset.go:223 +#, fuzzy +msgid "" +"Face ACL is not supported yet. Please use the WebTerminal to connect the " +"asset." +msgstr "" +"該端末は顔認証アクセスルールをサポートしていません。資産に接続するにはWebTerminalをご利用くだ" +"さい" + +#. lang.T +#. lang.T +#: pkg/handler/asset.go:238 pkg/handler/asset.go:247 +msgid "Unknown error code: %s, detail: %s" +msgstr "不明なエラーコード: %s, 詳細: %s" + #. lang.T -#: pkg/handler/asset.go:231 pkg/handler/asset.go:248 +#: pkg/handler/asset.go:258 msgid "get connect token err" msgstr "接続トークン取得エラー" @@ -236,10 +251,20 @@ msgstr "一致したユーザー名 %s が見つかりません" #. lang.T #. lang.T #. lang.T +#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 +#: pkg/handler/direct_handler.go:445 +#, fuzzy +msgid "" +"Face verification is not supported yet. Please use the WebTerminal to " +"connect the asset." +msgstr "" +"顔認証はまだサポートされていません。資産に接続するにはWebTerminalをご利用くだ" +"さい" + #. lang.T #. lang.T -#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 -#: pkg/handler/direct_handler.go:453 pkg/handler/direct_handler.go:469 +#. lang.T +#: pkg/handler/direct_handler.go:460 pkg/handler/direct_handler.go:476 #: pkg/handler/dispatch.go:139 msgid "Node: [ ID.Name(Asset amount) ]" msgstr "ノード: [ID.Name(アセット量)]" @@ -398,7 +423,7 @@ msgstr "" "接続に失敗しました。データベース接続設定が正しいか確認してください[Y/N]" #. lang.T -#: pkg/proxy/parser.go:282 +#: pkg/proxy/parser.go:283 #, fuzzy msgid "The command '%s' requires review. Continue or not [Y/n]?" msgstr "レビューアが確認します。継続するかどうか [Y/n]" @@ -406,7 +431,7 @@ msgstr "レビューアが確認します。継続するかどうか [Y/n]" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:302 pkg/proxy/parser.go:309 pkg/proxy/parser.go:463 +#: pkg/proxy/parser.go:303 pkg/proxy/parser.go:310 pkg/proxy/parser.go:463 msgid "Command `%s` is forbidden" msgstr "命令 `%s` は禁止されています" @@ -416,7 +441,7 @@ msgid "have no permission to download file" msgstr "ファイルをダウンロードする権限がない" #. lang.T -#: pkg/proxy/parser.go:608 +#: pkg/proxy/parser.go:606 msgid "" "Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C " "or CTRL+D." @@ -425,7 +450,7 @@ msgstr "" "るには、CTRL+C または CTRL+D を押してください。" #. lang.T -#: pkg/proxy/parser.go:618 +#: pkg/proxy/parser.go:616 msgid "" "Need ticket confirm to execute command, already send email to the reviewers" msgstr "" @@ -436,7 +461,7 @@ msgstr "" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:619 pkg/proxy/parser.go:620 pkg/proxy/server.go:58 +#: pkg/proxy/parser.go:617 pkg/proxy/parser.go:618 pkg/proxy/server.go:58 #: pkg/proxy/server.go:62 #, fuzzy msgid "" @@ -452,45 +477,45 @@ msgid "Account <%s> and asset <%s> protocol are inconsistent." msgstr "システムユーザ <%s> と資産 <%s> のプロトコルが一致しない" #. lang.T -#: pkg/proxy/server.go:101 +#: pkg/proxy/server.go:102 msgid "You don't have permission login %s" msgstr "ログイン権限がありません %s" #. lang.T -#: pkg/proxy/server.go:337 +#: pkg/proxy/server.go:334 msgid "You get auth token failed" msgstr "認証トークンの取得に失敗しました" #. lang.T -#: pkg/proxy/server.go:348 +#: pkg/proxy/server.go:345 msgid "Get auth password failed" msgstr "認証トークンの取得に失敗しました" #. lang.T #. lang.T -#: pkg/proxy/server.go:364 pkg/proxy/server.go:421 +#: pkg/proxy/server.go:361 pkg/proxy/server.go:418 msgid "Reuse SSH connections (%s@%s) [Number of connections: %d]" msgstr "SSH接続の再利用 (%s@%s) [接続数: %d]" #. lang.T -#: pkg/proxy/server.go:677 +#: pkg/proxy/server.go:674 msgid "Switched to %s" msgstr "%s に切り替え" #. lang.T #. lang.T -#: pkg/proxy/server.go:774 pkg/proxy/server.go:919 +#: pkg/proxy/server.go:771 pkg/proxy/server.go:916 msgid "Connect with api server failed" msgstr "APIサーバーとの接続に失敗しました" #. lang.T -#: pkg/proxy/server.go:968 +#: pkg/proxy/server.go:977 msgid "Start domain gateway failed %s" msgstr "ドメインゲートウェイの開始に失敗した %s" #. lang.T #. lang.T -#: pkg/proxy/server.go:976 pkg/proxy/server_options.go:108 +#: pkg/proxy/server.go:985 pkg/proxy/server_options.go:108 #, fuzzy msgid "Manual" msgstr "マニュアル" @@ -522,19 +547,19 @@ msgid "Connecting to Kubernetes %s container %s" msgstr "Kubernetes %s コンテナー %s への接続" #. lang.T -#: pkg/proxy/switch.go:325 +#: pkg/proxy/switch.go:328 #, fuzzy msgid "Session max time reached, disconnect" msgstr "セッションの最大時間に達しました。" #. lang.T #. lang.T -#: pkg/proxy/switch.go:336 pkg/proxy/switch.go:345 +#: pkg/proxy/switch.go:337 pkg/proxy/switch.go:344 msgid "Permission has expired, disconnect" msgstr "権限の有効期限が切れました。" #. lang.T -#: pkg/proxy/switch.go:357 +#: pkg/proxy/switch.go:354 msgid "Terminated by admin %s" msgstr "%s管理者が接続を終了" diff --git a/locale/zh_CN/LC_MESSAGES/koko.po b/locale/zh_CN/LC_MESSAGES/koko.po index 6bafff96..b801c4b4 100644 --- a/locale/zh_CN/LC_MESSAGES/koko.po +++ b/locale/zh_CN/LC_MESSAGES/koko.po @@ -97,8 +97,21 @@ msgid "ACL reject" msgstr "本次登录已拒绝,原因是访问控制策略的限制" #. lang.T +#: pkg/handler/asset.go:223 +#, fuzzy +msgid "" +"Face ACL is not supported yet. Please use the WebTerminal to connect the " +"asset." +msgstr "该终端不支持人脸访问规则,请使用web终端登录" + +#. lang.T +#. lang.T +#: pkg/handler/asset.go:238 pkg/handler/asset.go:247 +msgid "Unknown error code: %s, detail: %s" +msgstr "未知错误代码:%s,详情:%s" + #. lang.T -#: pkg/handler/asset.go:231 pkg/handler/asset.go:248 +#: pkg/handler/asset.go:258 msgid "get connect token err" msgstr "获取 connect token 错误" @@ -244,10 +257,18 @@ msgstr "未发现匹配的用户名 %s" #. lang.T #. lang.T #. lang.T +#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 +#: pkg/handler/direct_handler.go:445 +#, fuzzy +msgid "" +"Face verification is not supported yet. Please use the WebTerminal to " +"connect the asset." +msgstr "该终端不支持人脸识别认证,请使用web终端登录" + #. lang.T #. lang.T -#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 -#: pkg/handler/direct_handler.go:453 pkg/handler/direct_handler.go:469 +#. lang.T +#: pkg/handler/direct_handler.go:460 pkg/handler/direct_handler.go:476 #: pkg/handler/dispatch.go:139 msgid "Node: [ ID.Name(Asset amount) ]" msgstr "节点:[ ID.名称(资产数量) ]" @@ -411,7 +432,7 @@ msgid "" msgstr "您执行的命令存在风险,告警通知将发送给管理员。是否继续?[Y/N]" #. lang.T -#: pkg/proxy/parser.go:282 +#: pkg/proxy/parser.go:283 #, fuzzy msgid "The command '%s' requires review. Continue or not [Y/n]?" msgstr "命令 %s 需要复核,是否继续?[Y/N]" @@ -419,7 +440,7 @@ msgstr "命令 %s 需要复核,是否继续?[Y/N]" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:302 pkg/proxy/parser.go:309 pkg/proxy/parser.go:463 +#: pkg/proxy/parser.go:303 pkg/proxy/parser.go:310 pkg/proxy/parser.go:463 msgid "Command `%s` is forbidden" msgstr "命令 `%s` 是被禁止的 ..." @@ -429,7 +450,7 @@ msgid "have no permission to download file" msgstr "无权限下载文件" #. lang.T -#: pkg/proxy/parser.go:608 +#: pkg/proxy/parser.go:606 #, fuzzy msgid "" "Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C " @@ -437,7 +458,7 @@ msgid "" msgstr "请等待审核人复核命令 `%s`,取消按 CTRL+C 或 CTRL+D。" #. lang.T -#: pkg/proxy/parser.go:618 +#: pkg/proxy/parser.go:616 #, fuzzy msgid "" "Need ticket confirm to execute command, already send email to the reviewers" @@ -447,7 +468,7 @@ msgstr "需要工单命令执行复核,已发邮件通知审核人" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:619 pkg/proxy/parser.go:620 pkg/proxy/server.go:58 +#: pkg/proxy/parser.go:617 pkg/proxy/parser.go:618 pkg/proxy/server.go:58 #: pkg/proxy/server.go:62 #, fuzzy msgid "" @@ -461,47 +482,47 @@ msgid "Account <%s> and asset <%s> protocol are inconsistent." msgstr "系统用户<%s>和资产<%s>协议不一致" #. lang.T -#: pkg/proxy/server.go:101 +#: pkg/proxy/server.go:102 msgid "You don't have permission login %s" msgstr "你无权限登陆%s" #. lang.T -#: pkg/proxy/server.go:337 +#: pkg/proxy/server.go:334 msgid "You get auth token failed" msgstr "你获取认证令牌失败" #. lang.T -#: pkg/proxy/server.go:348 +#: pkg/proxy/server.go:345 #, fuzzy msgid "Get auth password failed" msgstr "你获取认证令牌失败" #. lang.T #. lang.T -#: pkg/proxy/server.go:364 pkg/proxy/server.go:421 +#: pkg/proxy/server.go:361 pkg/proxy/server.go:418 msgid "Reuse SSH connections (%s@%s) [Number of connections: %d]" msgstr "复用SSH连接(%s@%s)[连接数量: %d]" #. lang.T -#: pkg/proxy/server.go:677 +#: pkg/proxy/server.go:674 msgid "Switched to %s" msgstr "已切换至%s" #. lang.T #. lang.T -#: pkg/proxy/server.go:774 pkg/proxy/server.go:919 +#: pkg/proxy/server.go:771 pkg/proxy/server.go:916 msgid "Connect with api server failed" msgstr "连接API服务失败" #. lang.T -#: pkg/proxy/server.go:968 +#: pkg/proxy/server.go:977 #, fuzzy msgid "Start domain gateway failed %s" msgstr "启动数据库网关失败%s" #. lang.T #. lang.T -#: pkg/proxy/server.go:976 pkg/proxy/server_options.go:108 +#: pkg/proxy/server.go:985 pkg/proxy/server_options.go:108 #, fuzzy msgid "Manual" msgstr "手动账号" @@ -537,19 +558,19 @@ msgid "Connecting to Kubernetes %s container %s" msgstr "开始连接Kubernetes %s 容器 %s" #. lang.T -#: pkg/proxy/switch.go:325 +#: pkg/proxy/switch.go:328 #, fuzzy msgid "Session max time reached, disconnect" msgstr "会话超过最大连接时间,断开连接" #. lang.T #. lang.T -#: pkg/proxy/switch.go:336 pkg/proxy/switch.go:345 +#: pkg/proxy/switch.go:337 pkg/proxy/switch.go:344 msgid "Permission has expired, disconnect" msgstr "授权已过期,断开连接" #. lang.T -#: pkg/proxy/switch.go:357 +#: pkg/proxy/switch.go:354 #, fuzzy msgid "Terminated by admin %s" msgstr "%s 管理员终断连接" diff --git a/locale/zh_Hant/LC_MESSAGES/koko.po b/locale/zh_Hant/LC_MESSAGES/koko.po index 6255c231..7612ef22 100644 --- a/locale/zh_Hant/LC_MESSAGES/koko.po +++ b/locale/zh_Hant/LC_MESSAGES/koko.po @@ -97,8 +97,21 @@ msgid "ACL reject" msgstr "本次登入已拒絕,原因是訪問控制策略的限制" #. lang.T +#: pkg/handler/asset.go:223 +#, fuzzy +msgid "" +"Face ACL is not supported yet. Please use the WebTerminal to connect the " +"asset." +msgstr "該終端不支持人臉識別認證,請使用網頁終端登錄" + +#. lang.T +#. lang.T +#: pkg/handler/asset.go:238 pkg/handler/asset.go:247 +msgid "Unknown error code: %s, detail: %s" +msgstr "未知錯誤碼:%s,詳情:%s" + #. lang.T -#: pkg/handler/asset.go:231 pkg/handler/asset.go:248 +#: pkg/handler/asset.go:258 msgid "get connect token err" msgstr "獲取 connect token 錯誤" @@ -244,10 +257,18 @@ msgstr "未發現匹配的使用者名稱 %s" #. lang.T #. lang.T #. lang.T +#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 +#: pkg/handler/direct_handler.go:445 +#, fuzzy +msgid "" +"Face verification is not supported yet. Please use the WebTerminal to " +"connect the asset." +msgstr "該終端不支持人臉識別認證,請使用網頁終端登錄" + #. lang.T #. lang.T -#: pkg/handler/direct_handler.go:433 pkg/handler/direct_handler.go:439 -#: pkg/handler/direct_handler.go:453 pkg/handler/direct_handler.go:469 +#. lang.T +#: pkg/handler/direct_handler.go:460 pkg/handler/direct_handler.go:476 #: pkg/handler/dispatch.go:139 msgid "Node: [ ID.Name(Asset amount) ]" msgstr "節點:[ ID.名稱(資產數量) ]" @@ -411,7 +432,7 @@ msgid "" msgstr "您執行的指令存在風險,警告通知將發送給管理員。是否繼續?[Y/N]" #. lang.T -#: pkg/proxy/parser.go:282 +#: pkg/proxy/parser.go:283 #, fuzzy msgid "The command '%s' requires review. Continue or not [Y/n]?" msgstr "命令 `%s` 需要複核,是否繼續?[Y/N]" @@ -419,7 +440,7 @@ msgstr "命令 `%s` 需要複核,是否繼續?[Y/N]" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:302 pkg/proxy/parser.go:309 pkg/proxy/parser.go:463 +#: pkg/proxy/parser.go:303 pkg/proxy/parser.go:310 pkg/proxy/parser.go:463 msgid "Command `%s` is forbidden" msgstr "命令 `%s` 是被禁止的 ..." @@ -429,7 +450,7 @@ msgid "have no permission to download file" msgstr "無權限下載文件" #. lang.T -#: pkg/proxy/parser.go:608 +#: pkg/proxy/parser.go:606 #, fuzzy msgid "" "Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C " @@ -437,7 +458,7 @@ msgid "" msgstr "請等待審核人覆核命令 `%s`,取消按 CTRL+C 或 CTRL+D。" #. lang.T -#: pkg/proxy/parser.go:618 +#: pkg/proxy/parser.go:616 #, fuzzy msgid "" "Need ticket confirm to execute command, already send email to the reviewers" @@ -447,7 +468,7 @@ msgstr "需要工單命令執行覆核,已發郵件通知審核人" #. lang.T #. lang.T #. lang.T -#: pkg/proxy/parser.go:619 pkg/proxy/parser.go:620 pkg/proxy/server.go:58 +#: pkg/proxy/parser.go:617 pkg/proxy/parser.go:618 pkg/proxy/server.go:58 #: pkg/proxy/server.go:62 #, fuzzy msgid "" @@ -461,47 +482,47 @@ msgid "Account <%s> and asset <%s> protocol are inconsistent." msgstr "系統用戶<%s>和資產<%s>協議不一致" #. lang.T -#: pkg/proxy/server.go:101 +#: pkg/proxy/server.go:102 msgid "You don't have permission login %s" msgstr "你無權限登入 %s" #. lang.T -#: pkg/proxy/server.go:337 +#: pkg/proxy/server.go:334 msgid "You get auth token failed" msgstr "你獲取認證令牌失敗" #. lang.T -#: pkg/proxy/server.go:348 +#: pkg/proxy/server.go:345 #, fuzzy msgid "Get auth password failed" msgstr "你獲取認證令牌失敗" #. lang.T #. lang.T -#: pkg/proxy/server.go:364 pkg/proxy/server.go:421 +#: pkg/proxy/server.go:361 pkg/proxy/server.go:418 msgid "Reuse SSH connections (%s@%s) [Number of connections: %d]" msgstr "復用SSH連接(%s@%s)[連接數量: %d]" #. lang.T -#: pkg/proxy/server.go:677 +#: pkg/proxy/server.go:674 msgid "Switched to %s" msgstr "已切換至%s" #. lang.T #. lang.T -#: pkg/proxy/server.go:774 pkg/proxy/server.go:919 +#: pkg/proxy/server.go:771 pkg/proxy/server.go:916 msgid "Connect with api server failed" msgstr "連接API服務失敗" #. lang.T -#: pkg/proxy/server.go:968 +#: pkg/proxy/server.go:977 #, fuzzy msgid "Start domain gateway failed %s" msgstr "啟動資料庫網關失敗%s" #. lang.T #. lang.T -#: pkg/proxy/server.go:976 pkg/proxy/server_options.go:108 +#: pkg/proxy/server.go:985 pkg/proxy/server_options.go:108 #, fuzzy msgid "Manual" msgstr "手動帳號" @@ -537,19 +558,19 @@ msgid "Connecting to Kubernetes %s container %s" msgstr "開始連接Kubernetes %s 容器 %s" #. lang.T -#: pkg/proxy/switch.go:325 +#: pkg/proxy/switch.go:328 #, fuzzy msgid "Session max time reached, disconnect" msgstr "會話超過最大連接時間,斷開連接" #. lang.T #. lang.T -#: pkg/proxy/switch.go:336 pkg/proxy/switch.go:345 +#: pkg/proxy/switch.go:337 pkg/proxy/switch.go:344 msgid "Permission has expired, disconnect" msgstr "授權已過期,斷開連接" #. lang.T -#: pkg/proxy/switch.go:357 +#: pkg/proxy/switch.go:354 #, fuzzy msgid "Terminated by admin %s" msgstr "%s 管理員中斷連接" diff --git a/pkg/config/config.go b/pkg/config/config.go index d95393ad..951f5995 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -66,6 +66,8 @@ type Config struct { DisableInputAsCommand bool `mapstructure:"DISABLE_INPUT_AS_COMMAND"` + SecretEncryptKey string `mapstructure:"SECRET_ENCRYPT_KEY"` + RootPath string DataFolderPath string LogDirPath string @@ -82,6 +84,10 @@ func (c *Config) EnsureConfigValid() { } } +func (c *Config) UpdateRedisPassword(val string) { + c.RedisPassword = val +} + func GetConf() Config { if GlobalConfig == nil { return getDefaultConfig() diff --git a/pkg/handler/asset.go b/pkg/handler/asset.go index c400ca48..0f30224b 100644 --- a/pkg/handler/asset.go +++ b/pkg/handler/asset.go @@ -217,6 +217,13 @@ func (u *UserSelectHandler) proxyAsset(asset model.PermAsset) { utils.IgnoreErrWriteString(u.h.term, lang.T("ACL reject")) utils.IgnoreErrWriteString(u.h.term, utils.CharNewLine) return + case model.ACLFaceVerify, model.ACLFaceOnline, model.ACLFaceOnlineNotSupported: + // todo: 需要人脸验证 后续需要发站内信通知用户,并且等待用户人脸验证通过 + logger.Errorf("Create connect token and auth info failed: %s %s", tokenInfo.Code, tokenInfo.Detail) + msg := lang.T("Face ACL is not supported yet. Please use the WebTerminal to connect the asset.") + utils.IgnoreErrWriteString(u.h.term, msg) + utils.IgnoreErrWriteString(u.h.term, utils.CharNewLine) + return case model.ACLReview: reviewHandler := LoginReviewHandler{ readWriter: u.h.sess, @@ -237,6 +244,9 @@ func (u *UserSelectHandler) proxyAsset(asset model.PermAsset) { } tokenInfo = reviewHandler.tokenInfo default: + msg := lang.T("Unknown error code: %s, detail: %s") + utils.IgnoreErrWriteString(u.h.term, fmt.Sprintf(msg, tokenInfo.Code, tokenInfo.Detail)) + utils.IgnoreErrWriteString(u.h.term, utils.CharNewLine) logger.Errorf("Create connect token and auth info failed: %s %s", tokenInfo.Code, tokenInfo.Detail) return } diff --git a/pkg/handler/direct_handler.go b/pkg/handler/direct_handler.go index b7d49680..2951d610 100644 --- a/pkg/handler/direct_handler.go +++ b/pkg/handler/direct_handler.go @@ -439,6 +439,13 @@ func (d *DirectHandler) Proxy(asset model.PermAsset) { utils.IgnoreErrWriteString(d.term, lang.T("ACL reject")) utils.IgnoreErrWriteString(d.term, utils.CharNewLine) return + case model.ACLFaceVerify: + // todo: 需要人脸验证 后续需要发站内信通知用户,并且等待用户人脸验证通过 + logger.Errorf("Create connect token and auth info failed: %s %s", tokenInfo.Code, tokenInfo.Detail) + msg := lang.T("Face verification is not supported yet. Please use the WebTerminal to connect the asset.") + utils.IgnoreErrWriteString(d.term, msg) + utils.IgnoreErrWriteString(d.term, utils.CharNewLine) + return case model.ACLReview: reviewHandler := LoginReviewHandler{ readWriter: d.wrapperSess, diff --git a/pkg/handler/server_ssh.go b/pkg/handler/server_ssh.go index ed51a6bc..1b4fcaa1 100644 --- a/pkg/handler/server_ssh.go +++ b/pkg/handler/server_ssh.go @@ -412,7 +412,7 @@ func (s *Server) proxyAssetCommand(sess ssh.Session, sshClient *srvconn.SSHClien } ctx, cancel := context.WithCancel(sess.Context()) defer cancel() - + respSession.TokenId = tokenInfo.Id traceSession := session.NewSession(&respSession, func(task *model.TerminalTask) error { switch task.Name { case model.TaskKillSession: diff --git a/pkg/jms-sdk-go/model/token.go b/pkg/jms-sdk-go/model/token.go index 97bf2733..f8347330 100644 --- a/pkg/jms-sdk-go/model/token.go +++ b/pkg/jms-sdk-go/model/token.go @@ -23,8 +23,9 @@ type ConnectToken struct { CommandFilterACLs []CommandACL `json:"command_filter_acls"` - Ticket *ObjectId `json:"from_ticket,omitempty"` - TicketInfo interface{} `json:"from_ticket_info,omitempty"` + Ticket *ObjectId `json:"from_ticket,omitempty"` + TicketInfo interface{} `json:"from_ticket_info,omitempty"` + FaceMonitorToken string `json:"face_monitor_token,omitempty"` Code string `json:"code"` Detail string `json:"detail"` @@ -68,6 +69,10 @@ type ConnectTokenInfo struct { const ( ACLReview = "acl_review" ACLReject = "acl_reject" + + ACLFaceVerify = "acl_face_verify" + ACLFaceOnline = "acl_face_online" + ACLFaceOnlineNotSupported = "acl_face_online_not_supported" ) type ConnectOptions struct { diff --git a/pkg/jms-sdk-go/service/jms_face_callback.go b/pkg/jms-sdk-go/service/jms_face_callback.go new file mode 100644 index 00000000..7a5c150a --- /dev/null +++ b/pkg/jms-sdk-go/service/jms_face_callback.go @@ -0,0 +1,14 @@ +package service + +type JoinFaceMonitorRequest struct { + FaceMonitorToken string `json:"face_monitor_token"` + SessionId string `json:"session_id"` +} + +func (s *JMService) JoinFaceMonitor(result JoinFaceMonitorRequest) error { + var resp = map[string]interface{}{} + if _, err := s.authClient.Post(FaceMonitorContextUrl, &result, &resp); err != nil { + return err + } + return nil +} diff --git a/pkg/jms-sdk-go/service/jms_terminal.go b/pkg/jms-sdk-go/service/jms_terminal.go new file mode 100644 index 00000000..9b67bded --- /dev/null +++ b/pkg/jms-sdk-go/service/jms_terminal.go @@ -0,0 +1,14 @@ +package service + +func (s *JMService) GetEncryptedConfigValue(encryptKey, encryptedValue string) (resp ResultValue, err error) { + data := map[string]string{ + "secret_encrypt_key": encryptKey, + "encrypted_value": encryptedValue, + } + _, err = s.authClient.Post(TerminalEncryptedConfigURL, data, &resp) + return +} + +type ResultValue struct { + Value string `json:"value"` +} diff --git a/pkg/jms-sdk-go/service/url.go b/pkg/jms-sdk-go/service/url.go index d9af7c86..893e40d5 100644 --- a/pkg/jms-sdk-go/service/url.go +++ b/pkg/jms-sdk-go/service/url.go @@ -6,6 +6,8 @@ const ( TerminalRegisterURL = "/api/v1/terminal/terminal-registrations/" // 注册 TerminalConfigURL = "/api/v1/terminal/terminals/config/" // 获取配置 TerminalHeartBeatURL = "/api/v1/terminal/terminals/status/" + + TerminalEncryptedConfigURL = "/api/v1/terminal/encrypted-config/" ) // 用户登陆认证使用的API @@ -84,3 +86,6 @@ const ( const ( UserKoKoPreferenceURL = "/api/v1/users/preference/?category=koko" ) +const ( + FaceMonitorContextUrl = "/api/v1/authentication/face-monitor/context/" +) diff --git a/pkg/koko/koko.go b/pkg/koko/koko.go index 38d6cc0c..e1b8c320 100644 --- a/pkg/koko/koko.go +++ b/pkg/koko/koko.go @@ -40,6 +40,7 @@ func RunForever(confPath string) { gracefulStop := make(chan os.Signal, 1) signal.Notify(gracefulStop, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) jmsService := MustJMService() + bootstrapWithJMService(jmsService) webSrv := httpd.NewServer(jmsService) sshSrv := sshd.NewSSHServer(jmsService) app := &Koko{ @@ -55,9 +56,31 @@ func RunForever(confPath string) { func bootstrap() { i18n.Initial() logger.Initial() +} + +func bootstrapWithJMService(jmsService *service.JMService) { + updateEncryptConfigValue(jmsService) exchange.Initial() } +func updateEncryptConfigValue(jmsService *service.JMService) { + cfg := config.GlobalConfig + encryptKey := cfg.SecretEncryptKey + if encryptKey != "" { + redisPassword := cfg.RedisPassword + ret, err := jmsService.GetEncryptedConfigValue(encryptKey, redisPassword) + if err != nil { + logger.Error("Get encrypted config value failed: " + err.Error()) + return + } + if ret.Value != "" { + cfg.UpdateRedisPassword(ret.Value) + } else { + logger.Error("Get encrypted config value failed: empty value") + } + } +} + func runTasks(jmsService *service.JMService) { if config.GetConf().UploadFailedReplay { go uploadRemainReplay(jmsService) diff --git a/pkg/proxy/server.go b/pkg/proxy/server.go index 69991b8c..6d738832 100644 --- a/pkg/proxy/server.go +++ b/pkg/proxy/server.go @@ -929,6 +929,18 @@ func (s *Server) Proxy() { logger.Errorf("%s err: %s", msg, err) } } + if s.connOpts.authInfo.FaceMonitorToken != "" { + faceMonitorToken := s.connOpts.authInfo.FaceMonitorToken + faceReq := service.JoinFaceMonitorRequest{ + FaceMonitorToken: faceMonitorToken, + SessionId: s.sessionInfo.ID, + } + logger.Infof("Conn[%s] join face monitor %s", s.UserConn.ID(), faceMonitorToken) + if err := s.jmsService.JoinFaceMonitor(faceReq); err != nil { + logger.Errorf("Conn[%s] join face monitor err: %s", s.UserConn.ID(), err) + } + } + traceSession := session.NewSession(sw.p.sessionInfo, func(task *model.TerminalTask) error { switch task.Name { case model.TaskKillSession: diff --git a/pkg/srvconn/sftp_asset.go b/pkg/srvconn/sftp_asset.go index c42b8e2e..db383dc5 100644 --- a/pkg/srvconn/sftp_asset.go +++ b/pkg/srvconn/sftp_asset.go @@ -575,6 +575,7 @@ func (ad *AssetDir) createSftpSession(su *model.PermAccount) (sftpSess *SftpSess logger.Errorf("Create sftp Session err: %s", err1.Error()) return nil, err1 } + respSession.TokenId = conn.token.Id sftpSession := &SftpSession{SftpConn: conn, sess: &respSession, jmsService: ad.jmsService} terminalFunc := func(task *model.TerminalTask) error { switch task.Name { diff --git a/ui/src/hooks/useTerminal.ts b/ui/src/hooks/useTerminal.ts index 105ff59d..fca4e416 100644 --- a/ui/src/hooks/useTerminal.ts +++ b/ui/src/hooks/useTerminal.ts @@ -120,7 +120,7 @@ export const useTerminal = async (el: HTMLElement, option: ICallbackOptions): Pr } case 'CLOSE': { socket.close(); - sendEventToLuna('CLOSE', ''); + sendEventToLuna('CLOSE', '',lunaId.value, origin.value); break; } case 'PING':