diff --git a/.github/workflows/jms-build-test.yml b/.github/workflows/jms-build-test.yml index 5b1942cea..4760af7cf 100644 --- a/.github/workflows/jms-build-test.yml +++ b/.github/workflows/jms-build-test.yml @@ -3,6 +3,7 @@ on: push: paths: - 'Dockerfile' + - 'Dockerfile*' - 'Dockerfile-*' - 'pyproject.toml' - 'poetry.lock' @@ -10,46 +11,53 @@ on: jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + component: [core] + version: [v4] steps: - - uses: actions/checkout@v3 - - uses: docker/setup-qemu-action@v3 + - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - - name: Check Dockerfile + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Prepare Build run: | - test -f Dockerfile-ce || cp -f Dockerfile Dockerfile-ce + sed -i 's@^FROM registry.fit2cloud.com/jumpserver@FROM ghcr.io/jumpserver@g' Dockerfile-ee - name: Build CE Image uses: docker/build-push-action@v5 with: context: . - push: false - file: Dockerfile-ce - tags: jumpserver/core-ce:test + push: true + file: Dockerfile + tags: ghcr.io/jumpserver/${{ matrix.component }}:${{ matrix.version }}-ce platforms: linux/amd64 build-args: | + VERSION=${{ matrix.version }} APT_MIRROR=http://deb.debian.org PIP_MIRROR=https://pypi.org/simple - PIP_JMS_MIRROR=https://pypi.org/simple + outputs: type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true cache-from: type=gha cache-to: type=gha,mode=max - - name: Prepare EE Image - run: | - sed -i 's@^FROM registry.fit2cloud.com@# FROM registry.fit2cloud.com@g' Dockerfile-ee - sed -i 's@^COPY --from=build-xpack@# COPY --from=build-xpack@g' Dockerfile-ee - - name: Build EE Image uses: docker/build-push-action@v5 with: context: . push: false file: Dockerfile-ee - tags: jumpserver/core-ee:test + tags: ghcr.io/jumpserver/${{ matrix.component }}:${{ matrix.version }} platforms: linux/amd64 build-args: | + VERSION=${{ matrix.version }} APT_MIRROR=http://deb.debian.org PIP_MIRROR=https://pypi.org/simple - PIP_JMS_MIRROR=https://pypi.org/simple + outputs: type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true cache-from: type=gha cache-to: type=gha,mode=max \ No newline at end of file diff --git a/.gitignore b/.gitignore index b8fff0d67..df5709607 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ data/* test.py .history/ .test/ +*.mo diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62b3a9fca..4da32db08 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,10 @@ # Contributing +As a contributor, you should agree that: + +- The producer can adjust the open-source agreement to be more strict or relaxed as deemed necessary. +- Your contributed code may be used for commercial purposes, including but not limited to its cloud business operations. + ## Create pull request PR are always welcome, even if they only contain small fixes like typos or a few lines of code. If there will be a significant effort, please document it as an issue and get a discussion going before starting to work on it. diff --git a/Dockerfile-ce b/Dockerfile similarity index 53% rename from Dockerfile-ce rename to Dockerfile index 5714a5465..3bedb6867 100644 --- a/Dockerfile-ce +++ b/Dockerfile @@ -1,13 +1,49 @@ -FROM python:3.11-slim-bullseye as stage-1 +FROM debian:bullseye-slim as stage-1 ARG TARGETARCH +ARG DEPENDENCIES=" \ + ca-certificates \ + wget" + +ARG APT_MIRROR=http://mirrors.ustc.edu.cn +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \ + 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 \ + && apt-get update \ + && apt-get -y install --no-install-recommends ${DEPENDENCIES} \ + && echo "no" | dpkg-reconfigure dash + +WORKDIR /opt + +ARG CHECK_VERSION=v1.0.2 +RUN set -ex \ + && 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 \ + && mv check /usr/local/bin/ \ + && chown root:root /usr/local/bin/check \ + && chmod 755 /usr/local/bin/check \ + && rm -f check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz + +ARG RECEPTOR_VERSION=v1.4.5 +RUN set -ex \ + && wget -O /opt/receptor.tar.gz https://github.com/ansible/receptor/releases/download/${RECEPTOR_VERSION}/receptor_${RECEPTOR_VERSION/v/}_linux_${TARGETARCH}.tar.gz \ + && tar -xf /opt/receptor.tar.gz -C /usr/local/bin/ \ + && chown root:root /usr/local/bin/receptor \ + && chmod 755 /usr/local/bin/receptor \ + && rm -f /opt/receptor.tar.gz + ARG VERSION -ENV VERSION=$VERSION WORKDIR /opt/jumpserver ADD . . RUN echo > /opt/jumpserver/config.yml \ - && cd utils && bash -ixeu build.sh + && \ + if [ -n "${VERSION}" ]; then \ + sed -i "s@VERSION = .*@VERSION = '${VERSION}'@g" apps/jumpserver/const.py; \ + fi FROM python:3.11-slim-bullseye as stage-2 ARG TARGETARCH @@ -18,89 +54,69 @@ ARG BUILD_DEPENDENCIES=" \ pkg-config" ARG DEPENDENCIES=" \ + default-libmysqlclient-dev \ freetds-dev \ - libffi-dev \ - libjpeg-dev \ + gettext \ libkrb5-dev \ libldap2-dev \ - libpq-dev \ - libsasl2-dev \ - libssl-dev \ - libxml2-dev \ - libxmlsec1-dev \ - libxmlsec1-openssl \ - freerdp2-dev \ - libaio-dev" - -ARG TOOLS=" \ - ca-certificates \ - curl \ - default-libmysqlclient-dev \ - default-mysql-client \ - git \ - git-lfs \ - unzip \ - xz-utils \ - wget" + libsasl2-dev" ARG APT_MIRROR=http://mirrors.ustc.edu.cn -RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core-apt \ - --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core-apt \ - sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \ + set -ex \ && rm -f /etc/apt/apt.conf.d/docker-clean \ - && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ + && 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 \ && apt-get update \ && apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \ && apt-get -y install --no-install-recommends ${DEPENDENCIES} \ - && apt-get -y install --no-install-recommends ${TOOLS} \ && echo "no" | dpkg-reconfigure dash WORKDIR /opt/jumpserver ARG PIP_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple -RUN --mount=type=cache,target=/root/.cache \ - --mount=type=bind,source=poetry.lock,target=/opt/jumpserver/poetry.lock \ - --mount=type=bind,source=pyproject.toml,target=/opt/jumpserver/pyproject.toml \ +RUN --mount=type=cache,target=/root/.cache,sharing=locked,id=core \ + --mount=type=bind,source=poetry.lock,target=poetry.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ set -ex \ && python3 -m venv /opt/py3 \ && pip install poetry -i ${PIP_MIRROR} \ && poetry config virtualenvs.create false \ && . /opt/py3/bin/activate \ - && poetry install + && poetry install --only main + +COPY --from=stage-1 /opt/jumpserver /opt/jumpserver + +RUN set -ex \ + && export SECRET_KEY=$(head -c100 < /dev/urandom | base64 | tr -dc A-Za-z0-9 | head -c 48) \ + && . /opt/py3/bin/activate \ + && cd apps \ + && python manage.py compilemessages FROM python:3.11-slim-bullseye ARG TARGETARCH -ENV LANG=zh_CN.UTF-8 \ +ENV LANG=en_US.UTF-8 \ PATH=/opt/py3/bin:$PATH ARG DEPENDENCIES=" \ - libjpeg-dev \ - libpq-dev \ - libx11-dev \ - freerdp2-dev \ - libxmlsec1-openssl" + libldap2-dev \ + libx11-dev" ARG TOOLS=" \ ca-certificates \ - curl \ default-libmysqlclient-dev \ - default-mysql-client \ - iputils-ping \ - locales \ - netcat-openbsd \ - nmap \ openssh-client \ - patch \ sshpass \ - telnet \ - vim \ - wget" + bubblewrap" ARG APT_MIRROR=http://mirrors.ustc.edu.cn -RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core-apt \ - --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core-apt \ - sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \ + 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 -y install --no-install-recommends ${DEPENDENCIES} \ @@ -108,21 +124,12 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core-apt \ && mkdir -p /root/.ssh/ \ && echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n\tCiphers +aes128-cbc\n\tKexAlgorithms +diffie-hellman-group1-sha1\n\tHostKeyAlgorithms +ssh-rsa" > /root/.ssh/config \ && echo "no" | dpkg-reconfigure dash \ - && echo "zh_CN.UTF-8" | dpkg-reconfigure locales \ && sed -i "s@# export @export @g" ~/.bashrc \ && sed -i "s@# alias @alias @g" ~/.bashrc -ARG RECEPTOR_VERSION=v1.4.5 -RUN set -ex \ - && wget -O /opt/receptor.tar.gz https://github.com/ansible/receptor/releases/download/${RECEPTOR_VERSION}/receptor_${RECEPTOR_VERSION/v/}_linux_${TARGETARCH}.tar.gz \ - && tar -xf /opt/receptor.tar.gz -C /usr/local/bin/ \ - && chown root:root /usr/local/bin/receptor \ - && chmod 755 /usr/local/bin/receptor \ - && rm -f /opt/receptor.tar.gz - -COPY --from=stage-2 /opt/py3 /opt/py3 -COPY --from=stage-1 /opt/jumpserver/release/jumpserver /opt/jumpserver -COPY --from=stage-1 /opt/jumpserver/release/jumpserver/apps/libs/ansible/ansible.cfg /etc/ansible/ +COPY --from=stage-2 /opt /opt +COPY --from=stage-1 /usr/local/bin /usr/local/bin +COPY --from=stage-1 /opt/jumpserver/apps/libs/ansible/ansible.cfg /etc/ansible/ WORKDIR /opt/jumpserver @@ -131,6 +138,10 @@ ENV VERSION=$VERSION VOLUME /opt/jumpserver/data +ENTRYPOINT ["./entrypoint.sh"] + EXPOSE 8080 -ENTRYPOINT ["./entrypoint.sh"] +STOPSIGNAL SIGQUIT + +CMD ["start", "all"] diff --git a/Dockerfile-ee b/Dockerfile-ee index 2fbd4259d..ff29dd4d2 100644 --- a/Dockerfile-ee +++ b/Dockerfile-ee @@ -1,5 +1,52 @@ ARG VERSION -FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} as build-xpack -FROM registry.fit2cloud.com/jumpserver/core-ce:${VERSION} +FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} as build-xpack +FROM python:3.11-slim-bullseye as build-core +ARG BUILD_DEPENDENCIES=" \ + g++" + +ARG APT_MIRROR=http://mirrors.ustc.edu.cn +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \ + 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 \ + && apt-get update \ + && apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \ + && echo "no" | dpkg-reconfigure dash + +WORKDIR /opt/jumpserver + +ARG PIP_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple +RUN --mount=type=cache,target=/root/.cache,sharing=locked,id=core \ + --mount=type=bind,source=poetry.lock,target=/opt/jumpserver/poetry.lock \ + --mount=type=bind,source=pyproject.toml,target=/opt/jumpserver/pyproject.toml \ + set -ex \ + && python3 -m venv /opt/py3 \ + && pip install poetry -i ${PIP_MIRROR} \ + && poetry config virtualenvs.create false \ + && . /opt/py3/bin/activate \ + && poetry install --only xpack + +FROM registry.fit2cloud.com/jumpserver/core:${VERSION}-ce +ARG TARGETARCH + +ARG TOOLS=" \ + curl \ + iputils-ping \ + netcat-openbsd \ + nmap \ + telnet \ + vim \ + wget" + +ARG APT_MIRROR=http://mirrors.ustc.edu.cn +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \ + --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \ + set -ex \ + && apt-get update \ + && apt-get -y install --no-install-recommends ${TOOLS} + +COPY --from=build-core /opt/py3 /opt/py3 COPY --from=build-xpack /opt/xpack /opt/jumpserver/apps/xpack \ No newline at end of file diff --git a/README.md b/README.md index d9e8ff444..192958a4c 100644 --- a/README.md +++ b/README.md @@ -1,125 +1,112 @@ -

- JumpServer -

-

广受欢迎的开源堡垒机

+
+ + JumpServer + +## An open-source PAM tool (Bastion Host) -

- License: GPLv3 - Docker pulls - Latest release - Stars -

+[![][license-shield]][license-link] +[![][discord-shield]][discord-link] +[![][docker-shield]][docker-link] +[![][github-release-shield]][github-release-link] +[![][github-stars-shield]][github-stars-link] + +**English** · [简体中文](./README.zh-CN.md) · [Documents][docs-link] · [Report Bug][github-issues-link] · [Request Feature][github-issues-link] +
+
+ +## What is JumpServer? + +JumpServer is an open-source Privileged Access Management (PAM) tool that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and Remote App endpoints through a web browser. + +![JumpServer Overview](https://github.com/jumpserver/jumpserver/assets/41712985/eb9e6f39-3911-4d4a-bca9-aa50cc3b761d) + +## Screenshots + + + + + + + + + + + + + + + + + + + + +
JumpServer ConsoleJumpServer Audits
JumpServer WorkbenchJumpServer Settings
JumpServer SSHJumpServer RDP
JumpServer K8sJumpServer DB
+ +## Quick Start +Prepare a clean Linux Server ( 64bit, >= 4c8g ) + +``` +curl -sSL https://github.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash +``` + +Access JumpServer in your browser at `http://your-ip/`, `admin`/`admin` + +## Components + +JumpServer consists of multiple key components, which collectively form the functional framework of JumpServer, providing users with comprehensive capabilities for operations management and security control. + +| Project | Status | Description | +|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------| +| [Lina](https://github.com/jumpserver/lina) | Lina release | JumpServer Web UI | +| [Luna](https://github.com/jumpserver/luna) | Luna release | JumpServer Web Terminal | +| [KoKo](https://github.com/jumpserver/koko) | Koko release | JumpServer Character Protocol Connector | +| [Lion](https://github.com/jumpserver/lion) | Lion release | JumpServer Graphical Protocol Connector | +| [Chen](https://github.com/jumpserver/chen) | Chen release | JumpServer Web DB | +| [Razor](https://github.com/jumpserver/razor) | Chen | JumpServer RDP Proxy Connector | +| [Tinker](https://github.com/jumpserver/tinker) | Tinker | JumpServer Remote Application Connector (Windows) | +| [Panda](https://github.com/jumpserver/Panda) | Panda | JumpServer Remote Application Connector (Linux) | +| [Magnus](https://github.com/jumpserver/magnus) | Magnus | JumpServer Database Proxy Connector | -

- 9 年时间,倾情投入,用心做好一款开源堡垒机。 -

------------------------------- -JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。 +## Contributing -JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括: +Welcome to submit PR to contribute. Please refer to [CONTRIBUTING.md][contributing-link] for guidelines. -- **SSH**: Linux / Unix / 网络设备 等; -- **Windows**: Web 方式连接 / 原生 RDP 连接; -- **数据库**: MySQL / MariaDB / PostgreSQL / Oracle / SQLServer / ClickHouse 等; -- **NoSQL**: Redis / MongoDB 等; -- **GPT**: ChatGPT 等; -- **云服务**: Kubernetes / VMware vSphere 等; -- **Web 站点**: 各类系统的 Web 管理后台; -- **应用**: 通过 Remote App 连接各类应用。 +## Security -## 产品特色 +JumpServer is a mission critical product. Please refer to the Basic Security Recommendations for installation and deployment. If you encounter any security-related issues, please contact us directly: -- **开源**: 零门槛,线上快速获取和安装; -- **无插件**: 仅需浏览器,极致的 Web Terminal 使用体验; -- **分布式**: 支持分布式部署和横向扩展,轻松支持大规模并发访问; -- **多云支持**: 一套系统,同时管理不同云上面的资产; -- **多租户**: 一套系统,多个子公司或部门同时使用; -- **云端存储**: 审计录像云端存储,永不丢失; +- Email: support@fit2cloud.com -## UI 展示 - -![UI展示](https://docs.jumpserver.org/zh/v3/img/dashboard.png) - -## 在线体验 - -- 环境地址: - -| :warning: 注意 | -|:-----------------------------| -| 该环境仅作体验目的使用,我们会定时清理、重置数据! | -| 请勿修改体验环境用户的密码! | -| 请勿在环境中添加业务生产环境地址、用户名密码等敏感信息! | - -## 快速开始 - -- [快速入门](https://docs.jumpserver.org/zh/v3/quick_start/) -- [产品文档](https://docs.jumpserver.org) -- [在线学习](https://edu.fit2cloud.com/page/2635362) -- [知识库](https://kb.fit2cloud.com/categories/jumpserver) - -## 案例研究 - -- [腾讯音乐娱乐集团:基于JumpServer的安全运维审计解决方案](https://blog.fit2cloud.com/?p=a04cdf0d-6704-4d18-9b40-9180baecd0e2) -- [腾讯海外游戏:基于JumpServer构建游戏安全运营能力](https://blog.fit2cloud.com/?p=3704) -- [万华化学:通过JumpServer管理全球化分布式IT资产,并且实现与云管平台的联动](https://blog.fit2cloud.com/?p=3504) -- [雪花啤酒:JumpServer堡垒机使用体会](https://blog.fit2cloud.com/?p=3412) -- [顺丰科技:JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147) -- [沐瞳游戏:通过JumpServer管控多项目分布式资产](https://blog.fit2cloud.com/?p=3213) -- [携程:JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851) -- [大智慧:JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882) -- [小红书:JumpServer 堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516) -- [中手游:JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732) -- [中通快递:JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708) -- [东方明珠:JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687) -- [江苏农信:JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666) - -## 社区交流 - -如果您在使用过程中有任何疑问或对建议,欢迎提交 [GitHub Issue](https://github.com/jumpserver/jumpserver/issues/new/choose)。 - -您也可以到我们的 [社区论坛](https://bbs.fit2cloud.com/c/js/5) 当中进行交流沟通。 - -### 参与贡献 - -欢迎提交 PR 参与贡献。 参考 [CONTRIBUTING.md](https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md) - -## 组件项目 - -| 项目 | 状态 | 描述 | -|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------| -| [Lina](https://github.com/jumpserver/lina) |
Lina release | JumpServer Web UI 项目 | -| [Luna](https://github.com/jumpserver/luna) | Luna release | JumpServer Web Terminal 项目 | -| [KoKo](https://github.com/jumpserver/koko) | Koko release | JumpServer 字符协议 Connector 项目 | -| [Lion](https://github.com/jumpserver/lion-release) | Lion release | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) | -| [Razor](https://github.com/jumpserver/razor) | Chen | JumpServer RDP 代理 Connector 项目 | -| [Tinker](https://github.com/jumpserver/tinker) | Tinker | JumpServer 远程应用 Connector 项目 (Windows) | -| [Panda](https://github.com/jumpserver/Panda) | Panda | JumpServer 远程应用 Connector 项目 (Linux) | -| [Magnus](https://github.com/jumpserver/magnus-release) | Magnus release | JumpServer 数据库代理 Connector 项目 | -| [Chen](https://github.com/jumpserver/chen-release) | Chen release | JumpServer Web DB 项目,替代原来的 OmniDB | -| [Kael](https://github.com/jumpserver/kael) | Kael release | JumpServer 连接 GPT 资产的组件项目 | -| [Wisp](https://github.com/jumpserver/wisp) | Magnus release | JumpServer 各系统终端组件和 Core API 通信的组件项目 | -| [Clients](https://github.com/jumpserver/clients) | Clients release | JumpServer 客户端 项目 | -| [Installer](https://github.com/jumpserver/installer) | Installer release | JumpServer 安装包 项目 | - -## 安全说明 - -JumpServer是一款安全产品,请参考 [基本安全建议](https://docs.jumpserver.org/zh/master/install/install_security/) -进行安装部署。如果您发现安全相关问题,请直接联系我们: - -- 邮箱:support@fit2cloud.com -- 电话:400-052-0755 - -## License & Copyright +## License Copyright (c) 2014-2024 飞致云 FIT2CLOUD, All rights reserved. -Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at +Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.gnu.org/licenses/gpl-3.0.html -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an " -AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific -language governing permissions and limitations under the License. +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an " AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + +[docs-link]: https://en-docs.jumpserver.org/ +[discord-link]: https://discord.com/invite/jcM5tKWJ +[contributing-link]: https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md + + +[license-link]: https://www.gnu.org/licenses/gpl-3.0.html +[docker-link]: https://hub.docker.com/u/jumpserver +[github-release-link]: https://github.com/jumpserver/jumpserver/releases/latest +[github-stars-link]: https://github.com/jumpserver/jumpserver +[github-issues-link]: https://github.com/jumpserver/jumpserver/issues + + +[github-release-shield]: https://img.shields.io/github/v/release/jumpserver/jumpserver +[github-stars-shield]: https://img.shields.io/github/stars/jumpserver/jumpserver?color=%231890FF&style=flat-square +[docker-shield]: https://img.shields.io/docker/pulls/jumpserver/jms_all.svg +[license-shield]: https://img.shields.io/github/license/jumpserver/jumpserver +[discord-shield]: https://img.shields.io/discord/1194233267294052363?style=flat&logo=discord&logoColor=%23f5f5f5&labelColor=%235462eb&color=%235462eb + + diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 000000000..d9e8ff444 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,125 @@ +

+ JumpServer +

+

广受欢迎的开源堡垒机

+ +

+ License: GPLv3 + Docker pulls + Latest release + Stars +

+ + +

+ 9 年时间,倾情投入,用心做好一款开源堡垒机。 +

+ +------------------------------ +JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。 + +JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括: + +- **SSH**: Linux / Unix / 网络设备 等; +- **Windows**: Web 方式连接 / 原生 RDP 连接; +- **数据库**: MySQL / MariaDB / PostgreSQL / Oracle / SQLServer / ClickHouse 等; +- **NoSQL**: Redis / MongoDB 等; +- **GPT**: ChatGPT 等; +- **云服务**: Kubernetes / VMware vSphere 等; +- **Web 站点**: 各类系统的 Web 管理后台; +- **应用**: 通过 Remote App 连接各类应用。 + +## 产品特色 + +- **开源**: 零门槛,线上快速获取和安装; +- **无插件**: 仅需浏览器,极致的 Web Terminal 使用体验; +- **分布式**: 支持分布式部署和横向扩展,轻松支持大规模并发访问; +- **多云支持**: 一套系统,同时管理不同云上面的资产; +- **多租户**: 一套系统,多个子公司或部门同时使用; +- **云端存储**: 审计录像云端存储,永不丢失; + +## UI 展示 + +![UI展示](https://docs.jumpserver.org/zh/v3/img/dashboard.png) + +## 在线体验 + +- 环境地址: + +| :warning: 注意 | +|:-----------------------------| +| 该环境仅作体验目的使用,我们会定时清理、重置数据! | +| 请勿修改体验环境用户的密码! | +| 请勿在环境中添加业务生产环境地址、用户名密码等敏感信息! | + +## 快速开始 + +- [快速入门](https://docs.jumpserver.org/zh/v3/quick_start/) +- [产品文档](https://docs.jumpserver.org) +- [在线学习](https://edu.fit2cloud.com/page/2635362) +- [知识库](https://kb.fit2cloud.com/categories/jumpserver) + +## 案例研究 + +- [腾讯音乐娱乐集团:基于JumpServer的安全运维审计解决方案](https://blog.fit2cloud.com/?p=a04cdf0d-6704-4d18-9b40-9180baecd0e2) +- [腾讯海外游戏:基于JumpServer构建游戏安全运营能力](https://blog.fit2cloud.com/?p=3704) +- [万华化学:通过JumpServer管理全球化分布式IT资产,并且实现与云管平台的联动](https://blog.fit2cloud.com/?p=3504) +- [雪花啤酒:JumpServer堡垒机使用体会](https://blog.fit2cloud.com/?p=3412) +- [顺丰科技:JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147) +- [沐瞳游戏:通过JumpServer管控多项目分布式资产](https://blog.fit2cloud.com/?p=3213) +- [携程:JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851) +- [大智慧:JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882) +- [小红书:JumpServer 堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516) +- [中手游:JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732) +- [中通快递:JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708) +- [东方明珠:JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687) +- [江苏农信:JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666) + +## 社区交流 + +如果您在使用过程中有任何疑问或对建议,欢迎提交 [GitHub Issue](https://github.com/jumpserver/jumpserver/issues/new/choose)。 + +您也可以到我们的 [社区论坛](https://bbs.fit2cloud.com/c/js/5) 当中进行交流沟通。 + +### 参与贡献 + +欢迎提交 PR 参与贡献。 参考 [CONTRIBUTING.md](https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md) + +## 组件项目 + +| 项目 | 状态 | 描述 | +|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------| +| [Lina](https://github.com/jumpserver/lina) | Lina release | JumpServer Web UI 项目 | +| [Luna](https://github.com/jumpserver/luna) | Luna release | JumpServer Web Terminal 项目 | +| [KoKo](https://github.com/jumpserver/koko) | Koko release | JumpServer 字符协议 Connector 项目 | +| [Lion](https://github.com/jumpserver/lion-release) | Lion release | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) | +| [Razor](https://github.com/jumpserver/razor) | Chen | JumpServer RDP 代理 Connector 项目 | +| [Tinker](https://github.com/jumpserver/tinker) | Tinker | JumpServer 远程应用 Connector 项目 (Windows) | +| [Panda](https://github.com/jumpserver/Panda) | Panda | JumpServer 远程应用 Connector 项目 (Linux) | +| [Magnus](https://github.com/jumpserver/magnus-release) | Magnus release | JumpServer 数据库代理 Connector 项目 | +| [Chen](https://github.com/jumpserver/chen-release) | Chen release | JumpServer Web DB 项目,替代原来的 OmniDB | +| [Kael](https://github.com/jumpserver/kael) | Kael release | JumpServer 连接 GPT 资产的组件项目 | +| [Wisp](https://github.com/jumpserver/wisp) | Magnus release | JumpServer 各系统终端组件和 Core API 通信的组件项目 | +| [Clients](https://github.com/jumpserver/clients) | Clients release | JumpServer 客户端 项目 | +| [Installer](https://github.com/jumpserver/installer) | Installer release | JumpServer 安装包 项目 | + +## 安全说明 + +JumpServer是一款安全产品,请参考 [基本安全建议](https://docs.jumpserver.org/zh/master/install/install_security/) +进行安装部署。如果您发现安全相关问题,请直接联系我们: + +- 邮箱:support@fit2cloud.com +- 电话:400-052-0755 + +## License & Copyright + +Copyright (c) 2014-2024 飞致云 FIT2CLOUD, All rights reserved. + +Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in +compliance with the License. You may obtain a copy of the License at + +https://www.gnu.org/licenses/gpl-3.0.html + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an " +AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. diff --git a/README_EN.md b/README_EN.md deleted file mode 100644 index 16da1a8ca..000000000 --- a/README_EN.md +++ /dev/null @@ -1,94 +0,0 @@ -

JumpServer

-

Open Source Bastion Host

- -

- License: GPLv3 -  release - Codacy - Stars -

- -JumpServer is the world's first open-source Bastion Host and is licensed under the GPLv3. It is a 4A-compliant professional operation and maintenance security audit system. - -JumpServer uses Python / Django for development, follows Web 2.0 specifications, and is equipped with an industry-leading Web Terminal solution that provides a beautiful user interface and great user experience - -JumpServer adopts a distributed architecture to support multi-branch deployment across multiple cross-regional areas. The central node provides APIs, and login nodes are deployed in each branch. It can be scaled horizontally without concurrency restrictions. - -Change the world by taking every little step - ----- -### Advantages - -- Open Source: huge transparency and free to access with quick installation process. -- Distributed: support large-scale concurrent access with ease. -- No Plugin required: all you need is a browser, the ultimate Web Terminal experience. -- Multi-Cloud supported: a unified system to manage assets on different clouds at the same time -- Cloud storage: audit records are stored in the cloud. Data lost no more! -- Multi-Tenant system: multiple subsidiary companies or departments access the same system simultaneously. -- Many applications supported: link to databases, windows remote applications, and Kubernetes cluster, etc. - - -### JumpServer Component Projects -- [Lina](https://github.com/jumpserver/lina) JumpServer Web UI -- [Luna](https://github.com/jumpserver/luna) JumpServer Web Terminal -- [KoKo](https://github.com/jumpserver/koko) JumpServer Character protocaol Connector, replace original Python Version [Coco](https://github.com/jumpserver/coco) -- [Lion](https://github.com/jumpserver/lion-release) JumpServer Graphics protocol Connector,rely on [Apache Guacamole](https://guacamole.apache.org/) - -### Contribution -If you have any good ideas or helping us to fix bugs, please submit a Pull Request and accept our thanks :) - -Thanks to the following contributors for making JumpServer better everyday! - - - - - - - - - - - - - - - - - -### Thanks to -- [Apache Guacamole](https://guacamole.apache.org/) Web page connection RDP, SSH, VNC protocol equipment. JumpServer graphical connection dependent. -- [OmniDB](https://omnidb.org/) Web page connection to databases. JumpServer Web database dependent. - - -### JumpServer Enterprise Version -- [Apply for it](https://jinshuju.net/f/kyOYpi) - -### Case Study - -- [JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147); -- [JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882); -- [携程 JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851); -- [小红书的JumpServer堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516); -- [JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732); -- [中通快递:JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708); -- [东方明珠:JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687); -- [江苏农信:JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666)。 - -### For safety instructions - -JumpServer is a security product. Please refer to [Basic Security Recommendations](https://docs.jumpserver.org/zh/master/install/install_security/) for deployment and installation. - -If you find a security problem, please contact us directly: - -- ibuler@fit2cloud.com -- support@fit2cloud.com -- 400-052-0755 - -### License & Copyright -Copyright (c) 2014-2024 FIT2CLOUD Tech, Inc., All rights reserved. - -Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -https://www.gnu.org/licenses/gpl-3.0.htmll - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/apps/accounts/apps.py b/apps/accounts/apps.py index 56ca232f7..f24698b03 100644 --- a/apps/accounts/apps.py +++ b/apps/accounts/apps.py @@ -4,6 +4,7 @@ from django.apps import AppConfig class AccountsConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'accounts' + verbose_name = 'App Accounts' def ready(self): from . import signal_handlers # noqa diff --git a/apps/accounts/automations/backup_account/handlers.py b/apps/accounts/automations/backup_account/handlers.py index e2a0cdb3c..5ca137cd3 100644 --- a/apps/accounts/automations/backup_account/handlers.py +++ b/apps/accounts/automations/backup_account/handlers.py @@ -3,6 +3,7 @@ import time from collections import defaultdict, OrderedDict from django.conf import settings +from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from xlsxwriter import Workbook @@ -17,7 +18,7 @@ from terminal.models.component.storage import ReplayStorage from users.models import User PATH = os.path.join(os.path.dirname(settings.BASE_DIR), 'tmp') - +split_help_text = _('The account key will be split into two parts and sent') class RecipientsNotFound(Exception): pass @@ -115,8 +116,8 @@ class AssetAccountHandler(BaseAccountHandler): data = AccountSecretSerializer(_accounts, many=True).data cls.handler_secret(data, section) data_map.update(cls.add_rows(data, header_fields, sheet_name)) - - print('\n\033[33m- 共备份 {} 条账号\033[0m'.format(accounts.count())) + number_of_backup_accounts = _('Number of backup accounts') + print('\n\033[33m- {}: {}\033[0m'.format(number_of_backup_accounts, accounts.count())) return data_map @@ -127,9 +128,10 @@ class AccountBackupHandler: self.is_frozen = False # 任务状态冻结标志 def create_excel(self, section='complete'): + hint = _('Generating asset or application related backup information files') print( '\n' - '\033[32m>>> 正在生成资产或应用相关备份信息文件\033[0m' + f'\033[32m>>> {hint}\033[0m' '' ) # Print task start date @@ -151,7 +153,9 @@ class AccountBackupHandler: wb.close() files.append(filename) timedelta = round((time.time() - time_start), 2) - print('创建备份文件完成: 用时 {}s'.format(timedelta)) + time_cost = _('Time cost') + file_created = _('Backup file creation completed') + print('{}: {} {}s'.format(file_created, time_cost, timedelta)) return files def send_backup_mail(self, files, recipients): @@ -160,7 +164,7 @@ class AccountBackupHandler: recipients = User.objects.filter(id__in=list(recipients)) print( '\n' - '\033[32m>>> 开始发送备份邮件\033[0m' + f'\033[32m>>> {_("Start sending backup emails")}\033[0m' '' ) plan_name = self.plan_name @@ -172,7 +176,8 @@ class AccountBackupHandler: encrypt_and_compress_zip_file(attachment, user.secret_key, files) attachment_list = [attachment, ] AccountBackupExecutionTaskMsg(plan_name, user).publish(attachment_list) - print('邮件已发送至{}({})'.format(user, user.email)) + email_sent_to = _('Email sent to') + print('{} {}({})'.format(email_sent_to, user, user.email)) for file in files: os.remove(file) @@ -182,20 +187,22 @@ class AccountBackupHandler: recipients = ReplayStorage.objects.filter(id__in=list(recipients)) print( '\n' - '\033[32m>>> 开始发送备份文件到sftp服务器\033[0m' + '\033[32m>>> 📃 ---> sftp \033[0m' '' ) plan_name = self.plan_name + encrypt_file = _('Encrypting files using encryption password') for rec in recipients: attachment = os.path.join(PATH, f'{plan_name}-{local_now_filename()}-{time.time()}.zip') if password: - print('\033[32m>>> 使用加密密码对文件进行加密中\033[0m') + print(f'\033[32m>>> {encrypt_file}\033[0m') encrypt_and_compress_zip_file(attachment, password, files) else: zip_files(attachment, files) attachment_list = attachment AccountBackupByObjStorageExecutionTaskMsg(plan_name, rec).publish(attachment_list) - print('备份文件将发送至{}({})'.format(rec.name, rec.id)) + file_sent_to = _('The backup file will be sent to') + print('{}: {}({})'.format(file_sent_to, rec.name, rec.id)) for file in files: os.remove(file) @@ -203,14 +210,15 @@ class AccountBackupHandler: self.execution.reason = reason[:1024] self.execution.is_success = is_success self.execution.save() - print('\n已完成对任务状态的更新\n') + finish = _('Finish') + print(f'\n{finish}\n') @staticmethod def step_finished(is_success): if is_success: - print('任务执行成功') + print(_('Success')) else: - print('任务执行失败') + print(_('Failed')) def _run(self): is_success = False @@ -223,8 +231,6 @@ class AccountBackupHandler: self.backup_by_obj_storage() except Exception as e: self.is_frozen = True - print('任务执行被异常中断') - print('下面打印发生异常的 Traceback 信息 : ') print(e) error = str(e) else: @@ -239,15 +245,16 @@ class AccountBackupHandler: zip_encrypt_password = AccountBackupAutomation.objects.get(id=object_id).zip_encrypt_password obj_recipients_part_one = self.execution.snapshot.get('obj_recipients_part_one', []) obj_recipients_part_two = self.execution.snapshot.get('obj_recipients_part_two', []) + no_assigned_sftp_server = _('The backup task has no assigned sftp server') if not obj_recipients_part_one and not obj_recipients_part_two: print( '\n' - '\033[31m>>> 该备份任务未分配sftp服务器\033[0m' + f'\033[31m>>> {no_assigned_sftp_server}\033[0m' '' ) raise RecipientsNotFound('Not Found Recipients') if obj_recipients_part_one and obj_recipients_part_two: - print('\033[32m>>> 账号的密钥将被拆分成前后两部分发送\033[0m') + print(f'\033[32m>>> {split_help_text}\033[0m') files = self.create_excel(section='front') self.send_backup_obj_storage(files, obj_recipients_part_one, zip_encrypt_password) @@ -259,17 +266,19 @@ class AccountBackupHandler: self.send_backup_obj_storage(files, recipients, zip_encrypt_password) def backup_by_email(self): + + warn_text = _('The backup task has no assigned recipient') recipients_part_one = self.execution.snapshot.get('recipients_part_one', []) recipients_part_two = self.execution.snapshot.get('recipients_part_two', []) if not recipients_part_one and not recipients_part_two: print( '\n' - '\033[31m>>> 该备份任务未分配收件人\033[0m' + f'\033[31m>>> {warn_text}\033[0m' '' ) raise RecipientsNotFound('Not Found Recipients') if recipients_part_one and recipients_part_two: - print('\033[32m>>> 账号的密钥将被拆分成前后两部分发送\033[0m') + print(f'\033[32m>>> {split_help_text}\033[0m') files = self.create_excel(section='front') self.send_backup_mail(files, recipients_part_one) @@ -281,15 +290,18 @@ class AccountBackupHandler: self.send_backup_mail(files, recipients) def run(self): - print('任务开始: {}'.format(local_now_display())) + plan_start = _('Plan start') + plan_end = _('Plan end') + time_cost = _('Time cost') + error = _('An exception occurred during task execution') + print('{}: {}'.format(plan_start, local_now_display())) time_start = time.time() try: self._run() except Exception as e: - print('任务运行出现异常') - print('下面显示异常 Traceback 信息: ') + print(error) print(e) finally: - print('\n任务结束: {}'.format(local_now_display())) + print('\n{}: {}'.format(plan_end, local_now_display())) timedelta = round((time.time() - time_start), 2) - print('用时: {}s'.format(timedelta)) + print('{}: {}s'.format(time_cost, timedelta)) diff --git a/apps/accounts/automations/backup_account/manager.py b/apps/accounts/automations/backup_account/manager.py index f523803d5..f98bd9c9e 100644 --- a/apps/accounts/automations/backup_account/manager.py +++ b/apps/accounts/automations/backup_account/manager.py @@ -3,6 +3,7 @@ import time from django.utils import timezone +from django.utils.translation import gettext_lazy as _ from common.utils.timezone import local_now_display from .handlers import AccountBackupHandler @@ -19,7 +20,8 @@ class AccountBackupManager: def do_run(self): execution = self.execution - print('\n\033[33m# 账号备份计划正在执行\033[0m') + account_backup_execution_being_executed = _('The account backup plan is being executed') + print(f'\n\033[33m# {account_backup_execution_being_executed}\033[0m') handler = AccountBackupHandler(execution) handler.run() @@ -32,9 +34,11 @@ class AccountBackupManager: self.date_end = timezone.now() print('\n\n' + '-' * 80) - print('计划执行结束 {}\n'.format(local_now_display())) + plan_execution_end = _('Plan execution end') + print('{} {}\n'.format(plan_execution_end, local_now_display())) self.timedelta = self.time_end - self.time_start - print('用时: {}s'.format(self.timedelta)) + time_cost = _('Time cost') + print('{}: {}s'.format(time_cost, self.timedelta)) self.execution.timedelta = self.timedelta self.execution.save() diff --git a/apps/accounts/automations/change_secret/custom/ssh/main.yml b/apps/accounts/automations/change_secret/custom/ssh/main.yml index 42201392b..54707a7d5 100644 --- a/apps/accounts/automations/change_secret/custom/ssh/main.yml +++ b/apps/accounts/automations/change_secret/custom/ssh/main.yml @@ -13,11 +13,11 @@ login_password: "{{ jms_account.secret }}" login_secret_type: "{{ jms_account.secret_type }}" login_private_key_path: "{{ jms_account.private_key_path }}" - become: "{{ custom_become | default(False) }}" - become_method: "{{ custom_become_method | default('su') }}" - become_user: "{{ custom_become_user | default('') }}" - become_password: "{{ custom_become_password | default('') }}" - become_private_key_path: "{{ custom_become_private_key_path | default(None) }}" + become: "{{ jms_custom_become | default(False) }}" + become_method: "{{ jms_custom_become_method | default('su') }}" + become_user: "{{ jms_custom_become_user | default('') }}" + become_password: "{{ jms_custom_become_password | default('') }}" + become_private_key_path: "{{ jms_custom_become_private_key_path | default(None) }}" old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}" gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" register: ping_info @@ -31,11 +31,11 @@ login_port: "{{ jms_asset.port }}" login_secret_type: "{{ jms_account.secret_type }}" login_private_key_path: "{{ jms_account.private_key_path }}" - become: "{{ custom_become | default(False) }}" - become_method: "{{ custom_become_method | default('su') }}" - become_user: "{{ custom_become_user | default('') }}" - become_password: "{{ custom_become_password | default('') }}" - become_private_key_path: "{{ custom_become_private_key_path | default(None) }}" + become: "{{ jms_custom_become | default(False) }}" + become_method: "{{ jms_custom_become_method | default('su') }}" + become_user: "{{ jms_custom_become_user | default('') }}" + become_password: "{{ jms_custom_become_password | default('') }}" + become_private_key_path: "{{ jms_custom_become_private_key_path | default(None) }}" name: "{{ account.username }}" password: "{{ account.secret }}" commands: "{{ params.commands }}" diff --git a/apps/accounts/automations/change_secret/manager.py b/apps/accounts/automations/change_secret/manager.py index f08d01584..2a4432182 100644 --- a/apps/accounts/automations/change_secret/manager.py +++ b/apps/accounts/automations/change_secret/manager.py @@ -97,10 +97,9 @@ class ChangeSecretManager(AccountBasePlaybookManager): return host accounts = self.get_accounts(account) + error_msg = _("No pending accounts found") if not accounts: - print('没有发现待处理的账号: %s 用户ID: %s 类型: %s' % ( - asset.name, self.account_ids, self.secret_type - )) + print(f'{asset}: {error_msg}') return [] records = [] diff --git a/apps/accounts/automations/remove_account/database/mysql/main.yml b/apps/accounts/automations/remove_account/database/mysql/main.yml index 563a7d74b..a8700850f 100644 --- a/apps/accounts/automations/remove_account/database/mysql/main.yml +++ b/apps/accounts/automations/remove_account/database/mysql/main.yml @@ -2,6 +2,7 @@ gather_facts: no vars: ansible_python_interpreter: /opt/py3/bin/python + check_ssl: "{{ jms_asset.spec_info.use_ssl and not jms_asset.spec_info.allow_invalid_cert }}" tasks: - name: "Remove account" diff --git a/apps/accounts/automations/remove_account/host/posix/main.yml b/apps/accounts/automations/remove_account/host/posix/main.yml index cddac5541..e05e7693c 100644 --- a/apps/accounts/automations/remove_account/host/posix/main.yml +++ b/apps/accounts/automations/remove_account/host/posix/main.yml @@ -12,11 +12,13 @@ path: "{{ user_home_dir.stdout }}" register: home_dir when: user_home_dir.stdout != "" + ignore_errors: yes - name: "Rename user home directory if it exists" ansible.builtin.command: cmd: "mv {{ user_home_dir.stdout }} {{ user_home_dir.stdout }}.bak" when: home_dir.stat | default(false) and user_home_dir.stdout != "" + ignore_errors: yes - name: "Remove account" ansible.builtin.user: diff --git a/apps/accounts/migrations/0001_initial.py b/apps/accounts/migrations/0001_initial.py index 97ae584c4..c1bf3bd13 100644 --- a/apps/accounts/migrations/0001_initial.py +++ b/apps/accounts/migrations/0001_initial.py @@ -1,10 +1,8 @@ -# Generated by Django 3.2.14 on 2022-12-28 07:29 +# Generated by Django 4.1.13 on 2024-05-09 03:16 import uuid -import django.db.models.deletion import simple_history.models -from django.conf import settings from django.db import migrations, models import common.db.encoder @@ -12,11 +10,10 @@ import common.db.fields class Migration(migrations.Migration): + initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0098_auto_20220430_2126'), ] operations = [ @@ -29,63 +26,65 @@ class Migration(migrations.Migration): ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('connectivity', - models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', - max_length=16, verbose_name='Connectivity')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'OK'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), + ('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('name', models.CharField(max_length=128, verbose_name='Name')), ('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), ('privileged', models.BooleanField(default=False, verbose_name='Privileged')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), ('version', models.IntegerField(default=0, verbose_name='Version')), ('source', models.CharField(default='local', max_length=30, verbose_name='Source')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', - to='assets.asset', verbose_name='Asset')), - ('su_from', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', - to='accounts.account', verbose_name='Su from')), + ('source_id', models.CharField(blank=True, max_length=128, null=True, verbose_name='Source ID')), ], options={ 'verbose_name': 'Account', - 'permissions': [('view_accountsecret', 'Can view asset account secret'), - ('view_historyaccount', 'Can view asset history account'), - ('view_historyaccountsecret', 'Can view asset history account secret')], - 'unique_together': {('username', 'asset', 'secret_type'), ('name', 'asset')}, + 'permissions': [('view_accountsecret', 'Can view asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret'), ('verify_account', 'Can verify account'), ('push_account', 'Can push account'), ('remove_account', 'Can remove account')], }, ), migrations.CreateModel( - name='HistoricalAccount', + name='AccountBackupAutomation', fields=[ - ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), - ('version', models.IntegerField(default=0, verbose_name='Version')), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField(db_index=True)), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', - models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('history_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL)), + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), + ('types', models.JSONField(default=list)), + ('backup_type', models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email', max_length=128, verbose_name='Backup type')), + ('is_password_divided_by_email', models.BooleanField(default=True, verbose_name='Password divided')), + ('is_password_divided_by_obj_storage', models.BooleanField(default=True, verbose_name='Password divided')), + ('zip_encrypt_password', common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip encrypt password')), ], options={ - 'verbose_name': 'historical Account', - 'verbose_name_plural': 'historical Accounts', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': ('history_date', 'history_id'), + 'verbose_name': 'Account backup plan', + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='AccountBackupExecution', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')), + ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), + ('snapshot', models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Account backup snapshot')), + ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), + ('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')), + ('is_success', models.BooleanField(default=False, verbose_name='Is success')), + ], + options={ + 'verbose_name': 'Account backup execution', + 'ordering': ('-date_start',), }, - bases=(simple_history.models.HistoricalChanges, models.Model), ), migrations.CreateModel( name='AccountTemplate', @@ -96,23 +95,95 @@ class Migration(migrations.Migration): ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')), + ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), ('name', models.CharField(max_length=128, verbose_name='Name')), ('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), ('privileged', models.BooleanField(default=False, verbose_name='Privileged')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), + ('auto_push', models.BooleanField(default=False, verbose_name='Auto push')), + ('push_params', models.JSONField(default=dict, verbose_name='Push params')), ], options={ 'verbose_name': 'Account template', - 'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret'), - ('change_accounttemplatesecret', 'Can change asset account template secret')], - 'unique_together': {('name', 'org_id')}, + 'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret')], }, ), + migrations.CreateModel( + name='ChangeSecretRecord', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('old_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Old secret')), + ('new_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='New secret')), + ('date_started', models.DateTimeField(blank=True, null=True, verbose_name='Date started')), + ('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')), + ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), + ('error', models.TextField(blank=True, null=True, verbose_name='Error')), + ], + options={ + 'verbose_name': 'Change secret record', + 'ordering': ('-date_created',), + }, + ), + migrations.CreateModel( + name='GatheredAccount', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('present', models.BooleanField(default=True, verbose_name='Present')), + ('date_last_login', models.DateTimeField(null=True, verbose_name='Date login')), + ('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')), + ('address_last_login', models.CharField(default='', max_length=39, verbose_name='Address login')), + ], + options={ + 'verbose_name': 'Gather asset accounts', + 'ordering': ['asset'], + }, + ), + migrations.CreateModel( + name='HistoricalAccount', + fields=[ + ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), + ('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), + ('version', models.IntegerField(default=0, verbose_name='Version')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_date', models.DateTimeField(db_index=True)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ], + options={ + 'verbose_name': 'historical Account', + 'verbose_name_plural': 'historical Accounts', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': ('history_date', 'history_id'), + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='VirtualAccount', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('alias', models.CharField(choices=[('@INPUT', 'Manual input'), ('@USER', 'Dynamic user'), ('@ANON', 'Anonymous account'), ('@SPEC', 'Specified account')], max_length=128, verbose_name='Alias')), + ('secret_from_login', models.BooleanField(default=None, null=True, verbose_name='Secret from login')), + ], + ), ] diff --git a/apps/accounts/migrations/0002_auto_20220616_0021.py b/apps/accounts/migrations/0002_auto_20220616_0021.py index 155800064..5ac195d63 100644 --- a/apps/accounts/migrations/0002_auto_20220616_0021.py +++ b/apps/accounts/migrations/0002_auto_20220616_0021.py @@ -1,44 +1,103 @@ -# Generated by Django 3.2.14 on 2022-12-28 10:39 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import common.db.encoder -import common.db.fields -from django.conf import settings -from django.db import migrations, models import django.db.models.deletion -import uuid +from django.db import migrations, models + +import common.db.fields class Migration(migrations.Migration): + + initial = True + dependencies = [ - ('assets', '0106_auto_20221228_1838'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('assets', '0001_initial'), ('accounts', '0001_initial'), ] operations = [ migrations.CreateModel( - name='AccountBackupAutomation', + name='AccountBaseAutomation', fields=[ - ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic perform')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')), - ('types', models.JSONField(default=list)), - ('recipients', models.ManyToManyField(blank=True, related_name='recipient_escape_route_plans', - to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), ], options={ - 'verbose_name': 'Account backup plan', - 'ordering': ['name'], - 'unique_together': {('name', 'org_id')}, + 'verbose_name': 'Account automation task', + 'proxy': True, + 'indexes': [], + 'constraints': [], }, - ) + bases=('assets.baseautomation',), + ), + migrations.CreateModel( + name='AutomationExecution', + fields=[ + ], + options={ + 'verbose_name': 'Automation execution', + 'verbose_name_plural': 'Automation executions', + 'permissions': [('view_changesecretexecution', 'Can view change secret execution'), ('add_changesecretexecution', 'Can add change secret execution'), ('view_gatheraccountsexecution', 'Can view gather accounts execution'), ('add_gatheraccountsexecution', 'Can add gather accounts execution'), ('view_pushaccountexecution', 'Can view push account execution'), ('add_pushaccountexecution', 'Can add push account execution')], + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.automationexecution',), + ), + migrations.CreateModel( + name='ChangeSecretAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), + ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')), + ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), + ('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')), + ], + options={ + 'verbose_name': 'Change secret automation', + }, + bases=('accounts.accountbaseautomation', models.Model), + ), + migrations.CreateModel( + name='GatherAccountsAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ('is_sync_account', models.BooleanField(blank=True, default=False, verbose_name='Is sync account')), + ], + options={ + 'verbose_name': 'Gather account automation', + }, + bases=('accounts.accountbaseautomation',), + ), + migrations.CreateModel( + name='PushAccountAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), + ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')), + ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), + ('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')), + ('triggers', models.JSONField(default=list, max_length=16, verbose_name='Triggers')), + ('username', models.CharField(max_length=128, verbose_name='Username')), + ('action', models.CharField(max_length=16, verbose_name='Action')), + ], + options={ + 'verbose_name': 'Push asset account', + }, + bases=('accounts.accountbaseautomation', models.Model), + ), + migrations.CreateModel( + name='VerifyAccountAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Verify asset account', + }, + bases=('accounts.accountbaseautomation',), + ), + migrations.AlterUniqueTogether( + name='virtualaccount', + unique_together={('alias', 'org_id')}, + ), ] diff --git a/apps/accounts/migrations/0003_automation.py b/apps/accounts/migrations/0003_automation.py index 4840cc2ad..0ab6c3a8b 100644 --- a/apps/accounts/migrations/0003_automation.py +++ b/apps/accounts/migrations/0003_automation.py @@ -1,198 +1,116 @@ -# Generated by Django 3.2.16 on 2022-12-30 08:08 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import uuid - -import django.db.models.deletion from django.conf import settings from django.db import migrations, models - -import common.db.encoder -import common.db.fields +import django.db.models.deletion class Migration(migrations.Migration): + + initial = True + dependencies = [ - ('assets', '0107_automation'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('assets', '0001_initial'), + ('terminal', '0001_initial'), ('accounts', '0002_auto_20220616_0021'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.CreateModel( - name='AccountBaseAutomation', - fields=[ - ], - options={ - 'verbose_name': 'Account automation task', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.baseautomation',), + migrations.AddField( + model_name='historicalaccount', + name='history_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), ), - migrations.CreateModel( - name='AutomationExecution', - fields=[ - ], - options={ - 'verbose_name': 'Automation execution', - 'verbose_name_plural': 'Automation executions', - 'permissions': [('view_changesecretexecution', 'Can view change secret execution'), - ('add_changesecretexecution', 'Can add change secret execution'), - ('view_gatheraccountsexecution', 'Can view gather accounts execution'), - ('add_gatheraccountsexecution', 'Can add gather accounts execution')], - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.automationexecution',), + migrations.AddField( + model_name='gatheredaccount', + name='asset', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset', verbose_name='Asset'), ), - migrations.CreateModel( - name='PushAccountAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret_strategy', models.CharField(choices=[('specific', 'Specific password'), - ('random_one', 'All assets use the same random password'), - ('random_all', - 'All assets use different random password')], - default='specific', max_length=16, - verbose_name='Secret strategy')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), - ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), - ('ssh_key_change_strategy', models.CharField( - choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), - ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, - verbose_name='SSH key change strategy')), - ('triggers', models.JSONField(default=list, max_length=16, verbose_name='Triggers')), - ('username', models.CharField(max_length=128, verbose_name='Username')), - ('action', models.CharField(max_length=16, verbose_name='Action')), - ], - options={ - 'verbose_name': 'Push asset account', - }, - bases=('accounts.accountbaseautomation', models.Model), + migrations.AddField( + model_name='changesecretrecord', + name='account', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.account'), ), - - migrations.CreateModel( - name='GatherAccountsAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Gather asset accounts', - }, - bases=('accounts.accountbaseautomation',), + migrations.AddField( + model_name='changesecretrecord', + name='asset', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.asset'), ), - migrations.CreateModel( - name='VerifyAccountAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Verify asset account', - }, - bases=('accounts.accountbaseautomation',), + migrations.AddField( + model_name='changesecretrecord', + name='execution', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.automationexecution'), ), - migrations.CreateModel( - name='ChangeSecretRecord', - fields=[ - ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('old_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Old secret')), - ('new_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='New secret')), - ('date_started', models.DateTimeField(blank=True, null=True, verbose_name='Date started')), - ('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')), - ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), - ('error', models.TextField(blank=True, null=True, verbose_name='Error')), - ('account', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.account')), - ('asset', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.asset')), - ('execution', - models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.automationexecution')), - ], - options={ - 'verbose_name': 'Change secret record', - }, + migrations.AddField( + model_name='accounttemplate', + name='platforms', + field=models.ManyToManyField(blank=True, related_name='account_templates', to='assets.platform', verbose_name='Platforms'), ), - migrations.CreateModel( - name='AccountBackupExecution', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')), - ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), - ('plan_snapshot', - models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, - verbose_name='Account backup snapshot')), - ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], - default='manual', max_length=128, verbose_name='Trigger mode')), - ('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')), - ('is_success', models.BooleanField(default=False, verbose_name='Is success')), - ('plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution', - to='accounts.accountbackupautomation', verbose_name='Account backup plan')), - ], - options={ - 'verbose_name': 'Account backup execution', - 'ordering': ('-date_start',), - }, + migrations.AddField( + model_name='accounttemplate', + name='su_from', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.accounttemplate', verbose_name='Su from'), ), - migrations.CreateModel( - name='ChangeSecretAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret_strategy', models.CharField(choices=[('specific', 'Specific password'), - ('random_one', 'All assets use the same random password'), - ('random_all', - 'All assets use different random password')], - default='specific', max_length=16, - verbose_name='Secret strategy')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), - ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), - ('ssh_key_change_strategy', models.CharField( - choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), - ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, - verbose_name='SSH key change strategy')), - ('recipients', - models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), - ], - options={ - 'verbose_name': 'Change secret automation', - }, - bases=('accounts.accountbaseautomation', models.Model), + migrations.AddField( + model_name='accountbackupexecution', + name='plan', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution', to='accounts.accountbackupautomation', verbose_name='Account backup plan'), ), - migrations.AlterModelOptions( - name='automationexecution', - options={'permissions': [('view_changesecretexecution', 'Can view change secret execution'), - ('add_changesecretexecution', 'Can add change secret execution'), - ('view_gatheraccountsexecution', 'Can view gather accounts execution'), - ('add_gatheraccountsexecution', 'Can add gather accounts execution'), - ('view_pushaccountexecution', 'Can view push account execution'), - ('add_pushaccountexecution', 'Can add push account execution')], - 'verbose_name': 'Automation execution', 'verbose_name_plural': 'Automation executions'}, + migrations.AddField( + model_name='accountbackupautomation', + name='obj_recipients_part_one', + field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_one_plans', to='terminal.replaystorage', verbose_name='Object storage recipient part one'), ), - migrations.AlterModelOptions( - name='changesecretrecord', - options={'ordering': ('-date_started',), 'verbose_name': 'Change secret record'}, + migrations.AddField( + model_name='accountbackupautomation', + name='obj_recipients_part_two', + field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_two_plans', to='terminal.replaystorage', verbose_name='Object storage recipient part two'), + ), + migrations.AddField( + model_name='accountbackupautomation', + name='recipients_part_one', + field=models.ManyToManyField(blank=True, related_name='recipient_part_one_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient part one'), + ), + migrations.AddField( + model_name='accountbackupautomation', + name='recipients_part_two', + field=models.ManyToManyField(blank=True, related_name='recipient_part_two_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient part two'), + ), + migrations.AddField( + model_name='account', + name='asset', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='assets.asset', verbose_name='Asset'), + ), + migrations.AddField( + model_name='account', + name='su_from', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.account', verbose_name='Su from'), + ), + migrations.AlterUniqueTogether( + name='gatheredaccount', + unique_together={('username', 'asset')}, + ), + migrations.AddField( + model_name='gatheraccountsautomation', + name='recipients', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'), + ), + migrations.AddField( + model_name='changesecretautomation', + name='recipients', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'), + ), + migrations.AlterUniqueTogether( + name='accounttemplate', + unique_together={('name', 'org_id')}, + ), + migrations.AlterUniqueTogether( + name='accountbackupautomation', + unique_together={('name', 'org_id')}, + ), + migrations.AlterUniqueTogether( + name='account', + unique_together={('name', 'asset'), ('username', 'asset', 'secret_type')}, ), ] diff --git a/apps/accounts/migrations/0004_auto_20230106_1507.py b/apps/accounts/migrations/0004_auto_20230106_1507.py deleted file mode 100644 index 6392fce3b..000000000 --- a/apps/accounts/migrations/0004_auto_20230106_1507.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-06 07:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0003_automation'), - ] - - operations = [ - migrations.AlterField( - model_name='changesecretautomation', - name='secret_strategy', - field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'), - ), - migrations.AlterField( - model_name='pushaccountautomation', - name='secret_strategy', - field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'), - ), - ] diff --git a/apps/accounts/migrations/0005_alter_changesecretrecord_options.py b/apps/accounts/migrations/0005_alter_changesecretrecord_options.py deleted file mode 100644 index 67971198f..000000000 --- a/apps/accounts/migrations/0005_alter_changesecretrecord_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0004_auto_20230106_1507'), - ] - - operations = [ - migrations.AlterModelOptions( - name='changesecretrecord', - options={'ordering': ('-date_created',), 'verbose_name': 'Change secret record'}, - ), - ] diff --git a/apps/accounts/migrations/0006_gatheredaccount.py b/apps/accounts/migrations/0006_gatheredaccount.py deleted file mode 100644 index af0b2a048..000000000 --- a/apps/accounts/migrations/0006_gatheredaccount.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-07 04:41 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0108_alter_platform_charset'), - ('accounts', '0005_alter_changesecretrecord_options'), - ] - - operations = [ - migrations.CreateModel( - name='GatheredAccount', - fields=[ - ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('present', models.BooleanField(default=True, verbose_name='Present')), - ('date_last_login', models.DateTimeField(null=True, verbose_name='Date last login')), - ('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')), - ('address_last_login', models.CharField(default='', max_length=39, verbose_name='Address last login')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset', verbose_name='Asset')), - ], - options={ - 'verbose_name': 'Gather account', - 'ordering': ['asset'], - 'unique_together': {('username', 'asset')}, - }, - ), - ] diff --git a/apps/accounts/migrations/0007_alter_account_options.py b/apps/accounts/migrations/0007_alter_account_options.py deleted file mode 100644 index 6def6de6e..000000000 --- a/apps/accounts/migrations/0007_alter_account_options.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-16 11:07 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0006_gatheredaccount'), - ] - - operations = [ - migrations.AlterModelOptions( - name='account', - options={'permissions': [ - ('view_accountsecret', 'Can view asset account secret'), - ('view_historyaccount', 'Can view asset history account'), - ('view_historyaccountsecret', 'Can view asset history account secret'), - ('verify_account', 'Can verify account'), - ('push_account', 'Can push account'), - ('remove_account', 'Can remove account'), - ], 'verbose_name': 'Account'}, - ), - ] diff --git a/apps/accounts/migrations/0008_alter_gatheredaccount_options.py b/apps/accounts/migrations/0008_alter_gatheredaccount_options.py deleted file mode 100644 index d2600e700..000000000 --- a/apps/accounts/migrations/0008_alter_gatheredaccount_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-23 09:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0007_alter_account_options'), - ] - - operations = [ - migrations.AlterModelOptions( - name='gatheredaccount', - options={'ordering': ['asset'], 'verbose_name': 'Gather account automation'}, - ), - ] diff --git a/apps/accounts/migrations/0009_account_usernames_to_ids.py b/apps/accounts/migrations/0009_account_usernames_to_ids.py deleted file mode 100644 index 895176b4c..000000000 --- a/apps/accounts/migrations/0009_account_usernames_to_ids.py +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by Django 3.2.16 on 2023-03-07 07:36 - -from django.db import migrations -from django.db.models import Q - - -def get_nodes_all_assets(apps, *nodes): - node_model = apps.get_model('assets', 'Node') - asset_model = apps.get_model('assets', 'Asset') - node_ids = set() - descendant_node_query = Q() - for n in nodes: - node_ids.add(n.id) - descendant_node_query |= Q(key__istartswith=f'{n.key}:') - if descendant_node_query: - _ids = node_model.objects.order_by().filter(descendant_node_query).values_list('id', flat=True) - node_ids.update(_ids) - return asset_model.objects.order_by().filter(nodes__id__in=node_ids).distinct() - - -def get_all_assets(apps, snapshot): - node_model = apps.get_model('assets', 'Node') - asset_model = apps.get_model('assets', 'Asset') - asset_ids = snapshot.get('assets', []) - node_ids = snapshot.get('nodes', []) - - nodes = node_model.objects.filter(id__in=node_ids) - node_asset_ids = get_nodes_all_assets(apps, *nodes).values_list('id', flat=True) - asset_ids = set(list(asset_ids) + list(node_asset_ids)) - return asset_model.objects.filter(id__in=asset_ids) - - -def migrate_account_usernames_to_ids(apps, schema_editor): - db_alias = schema_editor.connection.alias - execution_model = apps.get_model('accounts', 'AutomationExecution') - account_model = apps.get_model('accounts', 'Account') - executions = execution_model.objects.using(db_alias).all() - executions_update = [] - for execution in executions: - snapshot = execution.snapshot - accounts = account_model.objects.none() - account_usernames = snapshot.get('accounts', []) - for asset in get_all_assets(apps, snapshot): - accounts = accounts | asset.accounts.all() - secret_type = snapshot.get('secret_type') - if secret_type: - ids = accounts.filter( - username__in=account_usernames, - secret_type=secret_type - ).values_list('id', flat=True) - else: - ids = accounts.filter( - username__in=account_usernames - ).values_list('id', flat=True) - snapshot['accounts'] = [str(_id) for _id in ids] - execution.snapshot = snapshot - executions_update.append(execution) - - execution_model.objects.bulk_update(executions_update, ['snapshot']) - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0008_alter_gatheredaccount_options'), - ] - - operations = [ - migrations.RunPython(migrate_account_usernames_to_ids), - ] diff --git a/apps/accounts/migrations/0010_gatheraccountsautomation_is_sync_account.py b/apps/accounts/migrations/0010_gatheraccountsautomation_is_sync_account.py deleted file mode 100644 index 259497692..000000000 --- a/apps/accounts/migrations/0010_gatheraccountsautomation_is_sync_account.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.16 on 2023-03-23 08:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0009_account_usernames_to_ids'), - ] - - operations = [ - migrations.AddField( - model_name='gatheraccountsautomation', - name='is_sync_account', - field=models.BooleanField(blank=True, default=False, verbose_name='Is sync account'), - ), - migrations.AddField( - model_name='account', - name='source_id', - field=models.CharField(max_length=128, null=True, blank=True, verbose_name='Source ID'), - ), - ] diff --git a/apps/accounts/migrations/0011_auto_20230506_1443.py b/apps/accounts/migrations/0011_auto_20230506_1443.py deleted file mode 100644 index 3460376bd..000000000 --- a/apps/accounts/migrations/0011_auto_20230506_1443.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-06 06:43 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0010_gatheraccountsautomation_is_sync_account'), - ] - - operations = [ - migrations.AddField( - model_name='accounttemplate', - name='su_from', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.accounttemplate', verbose_name='Su from'), - ), - migrations.AlterField( - model_name='changesecretautomation', - name='ssh_key_change_strategy', - field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'), - ), - migrations.AlterField( - model_name='pushaccountautomation', - name='ssh_key_change_strategy', - field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'), - ), - ] diff --git a/apps/accounts/migrations/0012_auto_20230621_1456.py b/apps/accounts/migrations/0012_auto_20230621_1456.py deleted file mode 100644 index 389e2b63d..000000000 --- a/apps/accounts/migrations/0012_auto_20230621_1456.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-21 06:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0011_auto_20230506_1443'), - ] - - operations = [ - migrations.RenameField( - model_name='account', - old_name='secret', - new_name='_secret', - ), - migrations.RenameField( - model_name='accounttemplate', - old_name='secret', - new_name='_secret', - ), - migrations.RenameField( - model_name='historicalaccount', - old_name='secret', - new_name='_secret', - ), - ] diff --git a/apps/accounts/migrations/0013_account_backup_recipients.py b/apps/accounts/migrations/0013_account_backup_recipients.py deleted file mode 100644 index 6fe03e349..000000000 --- a/apps/accounts/migrations/0013_account_backup_recipients.py +++ /dev/null @@ -1,77 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-03 08:28 -from django.conf import settings -from django.db import migrations, models - -import common.db.encoder - - -def migrate_recipients(apps, schema_editor): - account_backup_model = apps.get_model('accounts', 'AccountBackupAutomation') - execution_model = apps.get_model('accounts', 'AccountBackupExecution') - for account_backup in account_backup_model.objects.all(): - recipients = list(account_backup.recipients.all()) - if not recipients: - continue - account_backup.recipients_part_one.set(recipients) - - objs = [] - for execution in execution_model.objects.all(): - snapshot = execution.snapshot - recipients = snapshot.pop('recipients', {}) - snapshot.update({'recipients_part_one': recipients, 'recipients_part_two': {}}) - objs.append(execution) - execution_model.objects.bulk_update(objs, ['snapshot']) - - -def migrate_snapshot(apps, schema_editor): - model = apps.get_model('accounts', 'AccountBackupExecution') - objs = [] - for execution in model.objects.all(): - execution.snapshot = execution.plan_snapshot - objs.append(execution) - model.objects.bulk_update(objs, ['snapshot']) - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('accounts', '0012_auto_20230621_1456'), - ] - - operations = [ - migrations.AddField( - model_name='accountbackupautomation', - name='recipients_part_one', - field=models.ManyToManyField( - blank=True, related_name='recipient_part_one_plans', - to=settings.AUTH_USER_MODEL, verbose_name='Recipient part one' - ), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='recipients_part_two', - field=models.ManyToManyField( - blank=True, related_name='recipient_part_two_plans', - to=settings.AUTH_USER_MODEL, verbose_name='Recipient part two' - ), - ), - migrations.AddField( - model_name='accountbackupexecution', - name='snapshot', - field=models.JSONField( - default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, - null=True, blank=True, verbose_name='Account backup snapshot' - ), - ), - migrations.RunPython(migrate_snapshot), - migrations.RunPython(migrate_recipients), - migrations.RemoveField( - model_name='accountbackupexecution', - name='plan_snapshot', - ), - migrations.RemoveField( - model_name='accountbackupautomation', - name='recipients', - ), - - ] diff --git a/apps/accounts/migrations/0014_virtualaccount.py b/apps/accounts/migrations/0014_virtualaccount.py deleted file mode 100644 index df0159fc9..000000000 --- a/apps/accounts/migrations/0014_virtualaccount.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-01 09:12 - -import uuid - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0013_account_backup_recipients'), - ] - - operations = [ - migrations.CreateModel( - name='VirtualAccount', - fields=[ - ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('alias', models.CharField(choices=[('@INPUT', 'Manual input'), ('@USER', 'Dynamic user'), ('@ANON', 'Anonymous account'), ('@SPEC', 'Specified account')], max_length=128, verbose_name='Alias')), - ('secret_from_login', models.BooleanField(default=None, null=True, verbose_name='Secret from login')), - ], - options={ - 'unique_together': {('alias', 'org_id')}, - }, - ), - ] diff --git a/apps/accounts/migrations/0015_auto_20230825_1120.py b/apps/accounts/migrations/0015_auto_20230825_1120.py deleted file mode 100644 index 533613855..000000000 --- a/apps/accounts/migrations/0015_auto_20230825_1120.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-25 03:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0122_auto_20230803_1553'), - ('accounts', '0014_virtualaccount'), - ] - - operations = [ - migrations.AddField( - model_name='accounttemplate', - name='auto_push', - field=models.BooleanField(default=False, verbose_name='Auto push'), - ), - migrations.AddField( - model_name='accounttemplate', - name='platforms', - field=models.ManyToManyField(related_name='account_templates', to='assets.platform', verbose_name='Platforms', blank=True), - ), - migrations.AddField( - model_name='accounttemplate', - name='push_params', - field=models.JSONField(default=dict, verbose_name='Push params'), - ), - migrations.AddField( - model_name='accounttemplate', - name='secret_strategy', - field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'), - ), - ] diff --git a/apps/accounts/migrations/0016_accounttemplate_password_rules.py b/apps/accounts/migrations/0016_accounttemplate_password_rules.py deleted file mode 100644 index d036f90a4..000000000 --- a/apps/accounts/migrations/0016_accounttemplate_password_rules.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-18 08:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0015_auto_20230825_1120'), - ] - - operations = [ - migrations.AddField( - model_name='accounttemplate', - name='password_rules', - field=models.JSONField(default=dict, verbose_name='Password rules'), - ), - ] diff --git a/apps/accounts/migrations/0017_alter_automationexecution_options.py b/apps/accounts/migrations/0017_alter_automationexecution_options.py deleted file mode 100644 index a1f9f4dbb..000000000 --- a/apps/accounts/migrations/0017_alter_automationexecution_options.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-24 05:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0016_accounttemplate_password_rules'), - ] - - operations = [ - migrations.AlterModelOptions( - name='automationexecution', - options={ - 'permissions': [ - ('view_changesecretexecution', 'Can view change secret execution'), - ('add_changesecretexecution', 'Can add change secret execution'), - ('view_gatheraccountsexecution', 'Can view gather accounts execution'), - ('add_gatheraccountsexecution', 'Can add gather accounts execution'), - ('view_pushaccountexecution', 'Can view push account execution'), - ('add_pushaccountexecution', 'Can add push account execution') - ], - 'verbose_name': 'Automation execution', 'verbose_name_plural': 'Automation executions'}, - ), - ] diff --git a/apps/accounts/migrations/0018_accountbackupautomation_backup_type_and_more.py b/apps/accounts/migrations/0018_accountbackupautomation_backup_type_and_more.py deleted file mode 100644 index e7e04fb24..000000000 --- a/apps/accounts/migrations/0018_accountbackupautomation_backup_type_and_more.py +++ /dev/null @@ -1,45 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-03 07:10 - -import common.db.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0067_alter_replaystorage_type'), - ('accounts', '0017_alter_automationexecution_options'), - ] - - operations = [ - migrations.AddField( - model_name='accountbackupautomation', - name='backup_type', - field=models.CharField(choices=[('email', 'Email'), ('object_storage', 'Object Storage')], default='email', max_length=128), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='is_password_divided_by_email', - field=models.BooleanField(default=True), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='is_password_divided_by_obj_storage', - field=models.BooleanField(default=True), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='obj_recipients_part_one', - field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_one_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part one'), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='obj_recipients_part_two', - field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_two_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part two'), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='zip_encrypt_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip Encrypt Password'), - ), - ] diff --git a/apps/accounts/migrations/0019_gatheraccountsautomation_recipients.py b/apps/accounts/migrations/0019_gatheraccountsautomation_recipients.py deleted file mode 100644 index fa190f8ac..000000000 --- a/apps/accounts/migrations/0019_gatheraccountsautomation_recipients.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-31 06:12 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('accounts', '0018_accountbackupautomation_backup_type_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='gatheraccountsautomation', - name='recipients', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'), - ), - ] diff --git a/apps/accounts/migrations/0020_alter_accountbackupautomation_backup_type_and_more.py b/apps/accounts/migrations/0020_alter_accountbackupautomation_backup_type_and_more.py deleted file mode 100644 index 7e88fa547..000000000 --- a/apps/accounts/migrations/0020_alter_accountbackupautomation_backup_type_and_more.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-16 02:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0019_gatheraccountsautomation_recipients'), - ] - - operations = [ - migrations.AlterField( - model_name='accountbackupautomation', - name='backup_type', - field=models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email', max_length=128, verbose_name='Backup Type'), - ), - migrations.AlterField( - model_name='accountbackupautomation', - name='is_password_divided_by_email', - field=models.BooleanField(default=True, verbose_name='Is Password Divided'), - ), - migrations.AlterField( - model_name='accountbackupautomation', - name='is_password_divided_by_obj_storage', - field=models.BooleanField(default=True, verbose_name='Is Password Divided'), - ), - ] diff --git a/apps/accounts/models/automations/backup_account.py b/apps/accounts/models/automations/backup_account.py index 177e0dfa1..36c6fb1c2 100644 --- a/apps/accounts/models/automations/backup_account.py +++ b/apps/accounts/models/automations/backup_account.py @@ -24,9 +24,9 @@ logger = get_logger(__file__) class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel): types = models.JSONField(default=list) backup_type = models.CharField(max_length=128, choices=AccountBackupType.choices, - default=AccountBackupType.email.value, verbose_name=_('Backup Type')) - is_password_divided_by_email = models.BooleanField(default=True, verbose_name=_('Is Password Divided')) - is_password_divided_by_obj_storage = models.BooleanField(default=True, verbose_name=_('Is Password Divided')) + default=AccountBackupType.email.value, verbose_name=_('Backup type')) + is_password_divided_by_email = models.BooleanField(default=True, verbose_name=_('Password divided')) + is_password_divided_by_obj_storage = models.BooleanField(default=True, verbose_name=_('Password divided')) recipients_part_one = models.ManyToManyField( 'users.User', related_name='recipient_part_one_plans', blank=True, verbose_name=_("Recipient part one") @@ -37,14 +37,15 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel): ) obj_recipients_part_one = models.ManyToManyField( 'terminal.ReplayStorage', related_name='obj_recipient_part_one_plans', blank=True, - verbose_name=_("Object Storage Recipient part one") + verbose_name=_("Object storage recipient part one") ) obj_recipients_part_two = models.ManyToManyField( 'terminal.ReplayStorage', related_name='obj_recipient_part_two_plans', blank=True, - verbose_name=_("Object Storage Recipient part two") + verbose_name=_("Object storage recipient part two") + ) + zip_encrypt_password = fields.EncryptCharField( + max_length=4096, blank=True, null=True, verbose_name=_('Zip encrypt password') ) - zip_encrypt_password = fields.EncryptCharField(max_length=4096, blank=True, null=True, - verbose_name=_('Zip Encrypt Password')) def __str__(self): return f'{self.name}({self.org_id})' diff --git a/apps/accounts/models/automations/gather_account.py b/apps/accounts/models/automations/gather_account.py index bc56fa4ec..6a40a0498 100644 --- a/apps/accounts/models/automations/gather_account.py +++ b/apps/accounts/models/automations/gather_account.py @@ -12,10 +12,10 @@ __all__ = ['GatherAccountsAutomation', 'GatheredAccount'] class GatheredAccount(JMSOrgBaseModel): present = models.BooleanField(default=True, verbose_name=_("Present")) - date_last_login = models.DateTimeField(null=True, verbose_name=_("Date last login")) + date_last_login = models.DateTimeField(null=True, verbose_name=_("Date login")) asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, verbose_name=_("Asset")) username = models.CharField(max_length=32, blank=True, db_index=True, verbose_name=_('Username')) - address_last_login = models.CharField(max_length=39, default='', verbose_name=_("Address last login")) + address_last_login = models.CharField(max_length=39, default='', verbose_name=_("Address login")) @property def address(self): @@ -41,7 +41,7 @@ class GatheredAccount(JMSOrgBaseModel): Account.objects.bulk_create(account_objs) class Meta: - verbose_name = _('Gather account automation') + verbose_name = _("Gather asset accounts") unique_together = [ ('username', 'asset'), ] @@ -72,4 +72,4 @@ class GatherAccountsAutomation(AccountBaseAutomation): super().save(*args, **kwargs) class Meta: - verbose_name = _("Gather asset accounts") + verbose_name = _('Gather account automation') diff --git a/apps/accounts/models/template.py b/apps/accounts/models/template.py index 63ed1b20d..8d5be852a 100644 --- a/apps/accounts/models/template.py +++ b/apps/accounts/models/template.py @@ -29,7 +29,6 @@ class AccountTemplate(LabeledMixin, BaseAccount, SecretWithRandomMixin): ) permissions = [ ('view_accounttemplatesecret', _('Can view asset account template secret')), - ('change_accounttemplatesecret', _('Can change asset account template secret')), ] def __str__(self): diff --git a/apps/accounts/models/virtual.py b/apps/accounts/models/virtual.py index 88cf1b605..9b38d8d12 100644 --- a/apps/accounts/models/virtual.py +++ b/apps/accounts/models/virtual.py @@ -15,6 +15,7 @@ class VirtualAccount(JMSOrgBaseModel): class Meta: unique_together = [('alias', 'org_id')] + verbose_name = _('Virtual account') @property def name(self): diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index a885de52b..f3650e14b 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -31,7 +31,9 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer): default=False, label=_("Push now"), write_only=True ) params = serializers.JSONField( - decoder=None, encoder=None, required=False, style={'base_template': 'textarea.html'} + decoder=None, encoder=None, required=False, + style={'base_template': 'textarea.html'}, + label=_('Params'), ) on_invalid = LabeledChoiceField( choices=AccountInvalidPolicy.choices, default=AccountInvalidPolicy.ERROR, @@ -81,7 +83,7 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer): def get_template_attr_for_account(template): # Set initial data from template field_names = [ - 'name', 'username', 'secret', + 'name', 'username', 'secret', 'push_params', 'secret_type', 'privileged', 'is_active' ] @@ -90,7 +92,10 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer): value = getattr(template, name, None) if value is None: continue - attrs[name] = value + if name == 'push_params': + attrs['params'] = value + else: + attrs[name] = value attrs['secret'] = template.get_secret() return attrs @@ -225,7 +230,7 @@ class AccountSerializer(AccountCreateUpdateSerializerMixin, BaseAccountSerialize fields = BaseAccountSerializer.Meta.fields + [ 'su_from', 'asset', 'version', 'source', 'source_id', 'connectivity', - ] + list(set(AccountCreateUpdateSerializerMixin.Meta.fields) - {'params'}) + ] + AccountCreateUpdateSerializerMixin.Meta.fields read_only_fields = BaseAccountSerializer.Meta.read_only_fields + [ 'connectivity' ] diff --git a/apps/accounts/serializers/account/backup.py b/apps/accounts/serializers/account/backup.py index a67d834c6..d2aaf7ed1 100644 --- a/apps/accounts/serializers/account/backup.py +++ b/apps/accounts/serializers/account/backup.py @@ -35,8 +35,7 @@ class AccountBackupSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSer ] extra_kwargs = { 'name': {'required': True}, - 'periodic_display': {'label': _('Periodic perform')}, - 'executed_amount': {'label': _('Executed amount')}, + 'executed_amount': {'label': _('Executions')}, 'recipients': { 'label': _('Recipient'), 'help_text': _('Currently only mail sending is supported') diff --git a/apps/accounts/serializers/account/base.py b/apps/accounts/serializers/account/base.py index 9de35eb8c..7340b09df 100644 --- a/apps/accounts/serializers/account/base.py +++ b/apps/accounts/serializers/account/base.py @@ -9,26 +9,34 @@ from common.serializers import ResourceLabelsMixin from common.serializers.fields import EncryptedField, LabeledChoiceField from orgs.mixins.serializers import BulkOrgResourceModelSerializer -__all__ = ['AuthValidateMixin', 'BaseAccountSerializer'] +__all__ = ["AuthValidateMixin", "BaseAccountSerializer"] class AuthValidateMixin(serializers.Serializer): secret_type = LabeledChoiceField( - choices=SecretType.choices, label=_('Secret type'), default='password' + choices=SecretType.choices, label=_("Secret type"), default="password" ) secret = EncryptedField( - label=_('Secret'), required=False, max_length=40960, allow_blank=True, - allow_null=True, write_only=True, + label=_("Secret"), + required=False, + max_length=40960, + allow_blank=True, + allow_null=True, + write_only=True, ) passphrase = serializers.CharField( - allow_blank=True, allow_null=True, required=False, max_length=512, - write_only=True, label=_('Key password') + allow_blank=True, + allow_null=True, + required=False, + max_length=512, + write_only=True, + label=_("Passphrase"), ) @staticmethod def handle_secret(secret, secret_type, passphrase=None): if not secret: - return '' + return "" if secret_type == SecretType.PASSWORD: validate_password_for_ansible(secret) return secret @@ -40,17 +48,15 @@ class AuthValidateMixin(serializers.Serializer): return secret def clean_auth_fields(self, validated_data): - secret_type = validated_data.get('secret_type') - passphrase = validated_data.get('passphrase') - secret = validated_data.pop('secret', None) - validated_data['secret'] = self.handle_secret( - secret, secret_type, passphrase - ) - for field in ('secret',): + secret_type = validated_data.get("secret_type") + passphrase = validated_data.get("passphrase") + secret = validated_data.pop("secret", None) + validated_data["secret"] = self.handle_secret(secret, secret_type, passphrase) + for field in ("secret",): value = validated_data.get(field) if not value: validated_data.pop(field, None) - validated_data.pop('passphrase', None) + validated_data.pop("passphrase", None) def create(self, validated_data): self.clean_auth_fields(validated_data) @@ -61,22 +67,34 @@ class AuthValidateMixin(serializers.Serializer): return super().update(instance, validated_data) -class BaseAccountSerializer(AuthValidateMixin, ResourceLabelsMixin, BulkOrgResourceModelSerializer): +class BaseAccountSerializer( + AuthValidateMixin, ResourceLabelsMixin, BulkOrgResourceModelSerializer +): class Meta: model = BaseAccount - fields_mini = ['id', 'name', 'username'] + fields_mini = ["id", "name", "username"] fields_small = fields_mini + [ - 'secret_type', 'secret', 'passphrase', - 'privileged', 'is_active', + "secret_type", + "secret", + "passphrase", + "privileged", + "is_active", + "spec_info", ] - fields_other = ['created_by', 'date_created', 'date_updated', 'comment'] - fields = fields_small + fields_other + ['labels'] + fields_other = ["created_by", "date_created", "date_updated", "comment"] + fields = fields_small + fields_other + ["labels"] read_only_fields = [ - 'date_verified', 'created_by', 'date_created', + "spec_info", + "date_verified", + "created_by", + "date_created", ] extra_kwargs = { - 'username': {'help_text': _( - "Tip: If no username is required for authentication, fill in `null`, " - "If AD account, like `username@domain`" - )}, + "spec_info": {"label": _("Spec info")}, + "username": { + "help_text": _( + "* If no username is required for authentication, enter null. " + "For AD accounts, use the format username@domain." + ) + }, } diff --git a/apps/accounts/serializers/automations/base.py b/apps/accounts/serializers/automations/base.py index 1704c58a2..086f1b297 100644 --- a/apps/accounts/serializers/automations/base.py +++ b/apps/accounts/serializers/automations/base.py @@ -25,7 +25,8 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe class Meta: read_only_fields = [ - 'date_created', 'date_updated', 'created_by', 'periodic_display', 'executed_amount' + 'date_created', 'date_updated', 'created_by', + 'periodic_display', 'executed_amount' ] fields = read_only_fields + [ 'id', 'name', 'is_periodic', 'interval', 'crontab', 'comment', @@ -34,8 +35,7 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe extra_kwargs = { 'name': {'required': True}, 'type': {'read_only': True}, - 'periodic_display': {'label': _('Periodic perform')}, - 'executed_amount': {'label': _('Executed amount')}, + 'executed_amount': {'label': _('Executions')}, } def validate_name(self, name): diff --git a/apps/accounts/serializers/automations/change_secret.py b/apps/accounts/serializers/automations/change_secret.py index e3e9e2ce0..34d4326b8 100644 --- a/apps/accounts/serializers/automations/change_secret.py +++ b/apps/accounts/serializers/automations/change_secret.py @@ -54,10 +54,13 @@ class ChangeSecretAutomationSerializer(AuthValidateMixin, BaseAutomationSerializ 'ssh_key_change_strategy', 'passphrase', 'recipients', 'params' ] extra_kwargs = {**BaseAutomationSerializer.Meta.extra_kwargs, **{ - 'accounts': {'required': True}, + 'accounts': {'required': True, 'help_text': _('Please enter your account username')}, 'recipients': {'label': _('Recipient'), 'help_text': _( "Currently only mail sending is supported" )}, + 'params': {'help_text': _( + "Secret parameter settings, currently only effective for assets of the host type." + )}, }} @property diff --git a/apps/accounts/serializers/automations/push_account.py b/apps/accounts/serializers/automations/push_account.py index baf1994a4..b9982300b 100644 --- a/apps/accounts/serializers/automations/push_account.py +++ b/apps/accounts/serializers/automations/push_account.py @@ -7,7 +7,6 @@ from .change_secret import ( class PushAccountAutomationSerializer(ChangeSecretAutomationSerializer): - class Meta(ChangeSecretAutomationSerializer.Meta): model = PushAccountAutomation fields = [ diff --git a/apps/acls/apps.py b/apps/acls/apps.py index 291ce855e..e550e34e3 100644 --- a/apps/acls/apps.py +++ b/apps/acls/apps.py @@ -4,4 +4,4 @@ from django.utils.translation import gettext_lazy as _ class AclsConfig(AppConfig): name = 'acls' - verbose_name = _('Acls') + verbose_name = _('App Acls') diff --git a/apps/acls/const.py b/apps/acls/const.py index cccc906f4..3c03d8e2d 100644 --- a/apps/acls/const.py +++ b/apps/acls/const.py @@ -6,5 +6,5 @@ class ActionChoices(models.TextChoices): reject = 'reject', _('Reject') accept = 'accept', _('Accept') review = 'review', _('Review') - warning = 'warning', _('Warning') - notice = 'notice', _('Notifications') + warning = 'warning', _('Warn') + notice = 'notice', _('Notify') diff --git a/apps/acls/migrations/0001_initial.py b/apps/acls/migrations/0001_initial.py index 3d314387b..5d8394d5b 100644 --- a/apps/acls/migrations/0001_initial.py +++ b/apps/acls/migrations/0001_initial.py @@ -1,75 +1,129 @@ -# Generated by Django 3.1 on 2021-03-11 09:53 - -import uuid +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.fields import django.core.validators -import django.db.models.deletion -from django.conf import settings from django.db import migrations, models +import uuid class Migration(migrations.Migration): + initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='LoginACL', + name='CommandFilterACL', fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('ip_group', models.JSONField(default=list, verbose_name='Login IP')), - ('action', - models.CharField(choices=[('reject', 'Reject'), ('allow', 'Allow')], default='reject', max_length=64, - verbose_name='Action')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='login_acls', - to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('assets', common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets')), + ('accounts', models.JSONField(default=list, verbose_name='Accounts')), ], options={ + 'verbose_name': 'Command acl', 'ordering': ('priority', '-is_active', 'name'), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CommandGroup', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('type', models.CharField(choices=[('command', 'Command'), ('regex', 'Regex')], default='command', max_length=16, verbose_name='Type')), + ('content', models.TextField(help_text='One command per line', verbose_name='Content')), + ('ignore_case', models.BooleanField(default=True, verbose_name='Ignore case')), + ], + options={ + 'verbose_name': 'Command group', + }, + ), + migrations.CreateModel( + name='ConnectMethodACL', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('connect_methods', models.JSONField(default=list, verbose_name='Connect methods')), + ], + options={ + 'verbose_name': 'Connect method acl', + 'ordering': ('priority', '-is_active', 'name'), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LoginACL', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('rules', models.JSONField(default=dict, verbose_name='Rule')), + ], + options={ + 'verbose_name': 'Login acl', + 'ordering': ('priority', '-is_active', 'name'), + 'abstract': False, }, ), migrations.CreateModel( name='LoginAssetACL', fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('users', models.JSONField(verbose_name='User')), - ('system_users', models.JSONField(verbose_name='System User')), - ('assets', models.JSONField(verbose_name='Asset')), - ('action', - models.CharField(choices=[('login_confirm', 'Login confirm')], default='login_confirm', max_length=64, - verbose_name='Action')), - ('reviewers', - models.ManyToManyField(blank=True, related_name='review_login_asset_acls', to=settings.AUTH_USER_MODEL, - verbose_name='Reviewers')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('assets', common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets')), + ('accounts', models.JSONField(default=list, verbose_name='Accounts')), + ('rules', models.JSONField(default=dict, verbose_name='Rule')), ], options={ + 'verbose_name': 'Login asset acl', 'ordering': ('priority', '-is_active', 'name'), - 'unique_together': {('name', 'org_id')}, + 'abstract': False, }, ), ] diff --git a/apps/acls/migrations/0002_auto_20210926_1047.py b/apps/acls/migrations/0002_auto_20210926_1047.py index f2019a613..281bb758f 100644 --- a/apps/acls/migrations/0002_auto_20210926_1047.py +++ b/apps/acls/migrations/0002_auto_20210926_1047.py @@ -1,98 +1,54 @@ -# Generated by Django 3.1.12 on 2021-09-26 02:47 -import django +# Generated by Django 4.1.13 on 2024-05-09 03:16 + from django.conf import settings -from django.db import migrations, models, transaction - -LOGIN_CONFIRM_ZH = '登录复核' -LOGIN_CONFIRM_EN = 'Login confirm' - -DEFAULT_TIME_PERIODS = [{'id': i, 'value': '00:00~00:00'} for i in range(7)] - - -def has_zh(name: str) -> bool: - for i in name: - if u'\u4e00' <= i <= u'\u9fff': - return True - return False - - -def migrate_login_confirm(apps, schema_editor): - login_acl_model = apps.get_model("acls", "LoginACL") - login_confirm_model = apps.get_model("authentication", "LoginConfirmSetting") - - with transaction.atomic(): - for instance in login_confirm_model.objects.filter(is_active=True): - user = instance.user - reviewers = instance.reviewers.all() - login_confirm = LOGIN_CONFIRM_ZH if has_zh(user.name) else LOGIN_CONFIRM_EN - date_created = instance.date_created.strftime('%Y-%m-%d %H:%M:%S') - if reviewers.count() == 0: - continue - data = { - - 'user': user, - 'name': f'{user.name}-{login_confirm} ({date_created})', - 'created_by': instance.created_by, - 'action': 'confirm', - 'rules': {'ip_group': ['*'], 'time_period': DEFAULT_TIME_PERIODS} - } - instance = login_acl_model.objects.create(**data) - instance.reviewers.set(reviewers) - - -def migrate_ip_group(apps, schema_editor): - login_acl_model = apps.get_model("acls", "LoginACL") - updates = list() - with transaction.atomic(): - for instance in login_acl_model.objects.exclude(action='confirm'): - instance.rules = {'ip_group': instance.ip_group, 'time_period': DEFAULT_TIME_PERIODS} - updates.append(instance) - login_acl_model.objects.bulk_update(updates, ['rules', ]) +from django.db import migrations, models class Migration(migrations.Migration): + + initial = True + dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('acls', '0001_initial'), - ('authentication', '0004_ssotoken'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AlterField( - model_name='loginacl', - name='action', - field=models.CharField(choices=[('reject', 'Reject'), ('allow', 'Allow'), ('confirm', 'Login confirm')], - default='reject', max_length=64, verbose_name='Action'), + migrations.AddField( + model_name='loginassetacl', + name='reviewers', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), ), migrations.AddField( model_name='loginacl', name='reviewers', - field=models.ManyToManyField(blank=True, related_name='login_confirm_acls', - to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - migrations.AlterField( - model_name='loginacl', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, - related_name='login_acls', to=settings.AUTH_USER_MODEL, verbose_name='User'), + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), ), migrations.AddField( - model_name='loginacl', - name='rules', - field=models.JSONField(default=dict, verbose_name='Rule'), + model_name='connectmethodacl', + name='reviewers', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), ), - migrations.RunPython(migrate_login_confirm), - migrations.RunPython(migrate_ip_group), - migrations.RemoveField( - model_name='loginacl', - name='ip_group', + migrations.AlterUniqueTogether( + name='commandgroup', + unique_together={('org_id', 'name')}, ), - migrations.AlterModelOptions( - name='loginacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'}, + migrations.AddField( + model_name='commandfilteracl', + name='command_groups', + field=models.ManyToManyField(related_name='command_filters', to='acls.commandgroup', verbose_name='Command group'), ), - migrations.AlterModelOptions( + migrations.AddField( + model_name='commandfilteracl', + name='reviewers', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), + ), + migrations.AlterUniqueTogether( name='loginassetacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'}, + unique_together={('name', 'org_id')}, + ), + migrations.AlterUniqueTogether( + name='commandfilteracl', + unique_together={('name', 'org_id')}, ), ] diff --git a/apps/acls/migrations/0003_auto_20211130_1037.py b/apps/acls/migrations/0003_auto_20211130_1037.py deleted file mode 100644 index 9a975c684..000000000 --- a/apps/acls/migrations/0003_auto_20211130_1037.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.1.13 on 2021-11-30 02:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0002_auto_20210926_1047'), - ] - - operations = [ - migrations.AlterModelOptions( - name='loginacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'}, - ), - migrations.AlterModelOptions( - name='loginassetacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'}, - ), - ] diff --git a/apps/acls/migrations/0004_auto_20220831_1658.py b/apps/acls/migrations/0004_auto_20220831_1658.py deleted file mode 100644 index 6fd1ef86b..000000000 --- a/apps/acls/migrations/0004_auto_20220831_1658.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.13 on 2022-08-31 08:58 - -from django.db import migrations, models - - -def migrate_system_users_to_accounts(apps, schema_editor): - login_asset_acl_model = apps.get_model('acls', 'LoginAssetACL') - qs = login_asset_acl_model.objects.all() - login_asset_acls = [] - for instance in qs: - instance.accounts = instance.system_users - login_asset_acls.append(instance) - login_asset_acl_model.objects.bulk_update(login_asset_acls, ['accounts']) - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0003_auto_20211130_1037'), - ] - - operations = [ - migrations.AddField( - model_name='loginassetacl', - name='accounts', - field=models.JSONField(verbose_name='Account'), - ), - migrations.RunPython(migrate_system_users_to_accounts), - migrations.RemoveField( - model_name='loginassetacl', - name='system_users', - ), - - ] diff --git a/apps/acls/migrations/0005_auto_20221201_1846.py b/apps/acls/migrations/0005_auto_20221201_1846.py deleted file mode 100644 index 4885ea97e..000000000 --- a/apps/acls/migrations/0005_auto_20221201_1846.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-01 10:46 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('acls', '0004_auto_20220831_1658'), - ] - - operations = [ - migrations.AlterField( - model_name='loginacl', - name='action', - field=models.CharField(default='reject', max_length=64, verbose_name='Action'), - ), - migrations.AlterField( - model_name='loginacl', - name='reviewers', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - migrations.AlterField( - model_name='loginassetacl', - name='action', - field=models.CharField(default='reject', max_length=64, verbose_name='Action'), - ), - migrations.AlterField( - model_name='loginassetacl', - name='reviewers', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - ] diff --git a/apps/acls/migrations/0006_commandfilteracl_commandgroup.py b/apps/acls/migrations/0006_commandfilteracl_commandgroup.py deleted file mode 100644 index 3c1bd6793..000000000 --- a/apps/acls/migrations/0006_commandfilteracl_commandgroup.py +++ /dev/null @@ -1,70 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-01 11:39 - -import uuid - -import django.core.validators -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('acls', '0005_auto_20221201_1846'), - ] - - operations = [ - migrations.CreateModel( - name='CommandGroup', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('command', 'Command'), ('regex', 'Regex')], default='command', - max_length=16, verbose_name='Type')), - ('content', models.TextField(help_text='One line one command', verbose_name='Content')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('ignore_case', models.BooleanField(default=True, verbose_name='Ignore case')), - ], - options={ - 'verbose_name': 'Command filter rule', - 'unique_together': {('org_id', 'name')}, - }, - ), - migrations.CreateModel( - name='CommandFilterACL', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('users', models.JSONField(verbose_name='User')), - ('accounts', models.JSONField(verbose_name='Account')), - ('assets', models.JSONField(verbose_name='Asset')), - ('commands', models.ManyToManyField(to='acls.CommandGroup', verbose_name='Commands')), - ( - 'reviewers', - models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers')), - ], - options={ - 'verbose_name': 'Command acl', - 'ordering': ('priority', '-is_active', 'name'), - 'unique_together': {('name', 'org_id')}, - }, - ), - ] diff --git a/apps/acls/migrations/0007_auto_20221202_1048.py b/apps/acls/migrations/0007_auto_20221202_1048.py deleted file mode 100644 index 1a61a4ff4..000000000 --- a/apps/acls/migrations/0007_auto_20221202_1048.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-02 02:48 - -from django.db import migrations - - -def migrate_login_type(apps, schema_editor): - login_asset_model = apps.get_model('acls', 'LoginAssetACL') - login_asset_model.objects.filter(action='login_confirm').update(action='review') - - login_system_model = apps.get_model('acls', 'LoginACL') - login_system_model.objects.filter(action='confirm').update(action='review') - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0006_commandfilteracl_commandgroup'), - ] - - operations = [ - migrations.RunPython(migrate_login_type), - ] diff --git a/apps/acls/migrations/0008_commandgroup_comment.py b/apps/acls/migrations/0008_commandgroup_comment.py deleted file mode 100644 index 0764daa22..000000000 --- a/apps/acls/migrations/0008_commandgroup_comment.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-02 04:25 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0007_auto_20221202_1048'), - ] - - operations = [ - migrations.AlterModelOptions( - name='commandgroup', - options={'verbose_name': 'Command group'}, - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='commands', - new_name='command_groups', - ), - migrations.AlterModelOptions( - name='commandfilteracl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Command acl'}, - ), - migrations.AlterModelOptions( - name='loginacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'}, - ), - migrations.AlterModelOptions( - name='loginassetacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'}, - ), - ] diff --git a/apps/acls/migrations/0009_auto_20221220_1956.py b/apps/acls/migrations/0009_auto_20221220_1956.py deleted file mode 100644 index 78f8b1152..000000000 --- a/apps/acls/migrations/0009_auto_20221220_1956.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('acls', '0008_commandgroup_comment'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilteracl', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='loginacl', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='loginassetacl', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='commandfilteracl', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='commandgroup', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='commandgroup', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='loginacl', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='loginassetacl', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/acls/migrations/0010_alter_commandfilteracl_command_groups.py b/apps/acls/migrations/0010_alter_commandfilteracl_command_groups.py deleted file mode 100644 index b657906f1..000000000 --- a/apps/acls/migrations/0010_alter_commandfilteracl_command_groups.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('acls', '0009_auto_20221220_1956'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilteracl', - name='command_groups', - field=models.ManyToManyField(to='acls.CommandGroup', verbose_name='Command group'), - ), - ] diff --git a/apps/acls/migrations/0011_auto_20230425_1704.py b/apps/acls/migrations/0011_auto_20230425_1704.py deleted file mode 100644 index f5d7dee6c..000000000 --- a/apps/acls/migrations/0011_auto_20230425_1704.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-25 09:04 - -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0010_alter_commandfilteracl_command_groups'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilteracl', - name='new_accounts', - field=models.JSONField(default=list, verbose_name='Accounts'), - ), - migrations.AddField( - model_name='commandfilteracl', - name='new_assets', - field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AddField( - model_name='commandfilteracl', - name='new_users', - field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'), - ), - migrations.AddField( - model_name='loginassetacl', - name='new_accounts', - field=models.JSONField(default=list, verbose_name='Accounts') - ), - migrations.AddField( - model_name='loginassetacl', - name='new_assets', - field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AddField( - model_name='loginassetacl', - name='new_users', - field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'), - ), - ] diff --git a/apps/acls/migrations/0012_auto_20230426_1111.py b/apps/acls/migrations/0012_auto_20230426_1111.py deleted file mode 100644 index c0e225138..000000000 --- a/apps/acls/migrations/0012_auto_20230426_1111.py +++ /dev/null @@ -1,41 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-26 03:11 - -from django.db import migrations - - -def migrate_base_acl_users_assets_accounts(apps, *args): - cmd_acl_model = apps.get_model('acls', 'CommandFilterACL') - login_asset_acl_model = apps.get_model('acls', 'LoginAssetACL') - - for model in [cmd_acl_model, login_asset_acl_model]: - for obj in model.objects.all(): - user_names = (obj.users or {}).get('username_group', []) - obj.new_users = { - "type": "attrs", - "attrs": [{"name": "username", "value": user_names, "match": "in"}] - } - - asset_names = (obj.assets or {}).get('name_group', []) - asset_attrs = [] - if asset_names: - asset_attrs.append({"name": "name", "value": asset_names, "match": "in"}) - asset_address = (obj.assets or {}).get('address_group', []) - if asset_address: - asset_attrs.append({"name": "address", "value": asset_address, "match": "ip_in"}) - obj.new_assets = {"type": "attrs", "attrs": asset_attrs} - - account_usernames = (obj.accounts or {}).get('username_group', []) - if '*' in account_usernames: - account_usernames = ['@ALL'] - obj.new_accounts = account_usernames - obj.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0011_auto_20230425_1704'), - ] - - operations = [ - migrations.RunPython(migrate_base_acl_users_assets_accounts) - ] diff --git a/apps/acls/migrations/0013_auto_20230426_1759.py b/apps/acls/migrations/0013_auto_20230426_1759.py deleted file mode 100644 index 56dd58446..000000000 --- a/apps/acls/migrations/0013_auto_20230426_1759.py +++ /dev/null @@ -1,66 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-26 09:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0012_auto_20230426_1111'), - ] - - operations = [ - migrations.RemoveField( - model_name='commandfilteracl', - name='accounts', - ), - migrations.RemoveField( - model_name='commandfilteracl', - name='assets', - ), - migrations.RemoveField( - model_name='commandfilteracl', - name='users', - ), - migrations.RemoveField( - model_name='loginassetacl', - name='accounts', - ), - migrations.RemoveField( - model_name='loginassetacl', - name='assets', - ), - migrations.RemoveField( - model_name='loginassetacl', - name='users', - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='new_accounts', - new_name='accounts', - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='new_assets', - new_name='assets', - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='new_users', - new_name='users', - ), - migrations.RenameField( - model_name='loginassetacl', - old_name='new_accounts', - new_name='accounts', - ), - migrations.RenameField( - model_name='loginassetacl', - old_name='new_assets', - new_name='assets', - ), - migrations.RenameField( - model_name='loginassetacl', - old_name='new_users', - new_name='users', - ), - ] diff --git a/apps/acls/migrations/0014_loginassetacl_rules.py b/apps/acls/migrations/0014_loginassetacl_rules.py deleted file mode 100644 index d7574ffd0..000000000 --- a/apps/acls/migrations/0014_loginassetacl_rules.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-26 09:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('acls', '0013_auto_20230426_1759'), - ] - - operations = [ - migrations.AddField( - model_name='loginassetacl', - name='rules', - field=models.JSONField(default=dict, verbose_name='Rule'), - ), - ] diff --git a/apps/acls/migrations/0015_connectmethodacl.py b/apps/acls/migrations/0015_connectmethodacl.py deleted file mode 100644 index 5d5e3ff8c..000000000 --- a/apps/acls/migrations/0015_connectmethodacl.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-06 06:23 - -import uuid - -import django.core.validators -from django.conf import settings -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('acls', '0014_loginassetacl_rules'), - ] - - operations = [ - migrations.CreateModel( - name='ConnectMethodACL', - fields=[ - ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), - ('connect_methods', models.JSONField(default=list, verbose_name='Connect methods')), - ( - 'reviewers', - models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers')), - ], - options={ - 'ordering': ('priority', '-is_active', 'name'), - 'abstract': False, - }, - ), - ] diff --git a/apps/acls/migrations/0016_auto_20230606_1857.py b/apps/acls/migrations/0016_auto_20230606_1857.py deleted file mode 100644 index d703dac52..000000000 --- a/apps/acls/migrations/0016_auto_20230606_1857.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-06 10:57 - -from django.db import migrations, models - -import common.db.fields - - -def migrate_users_login_acls(apps, schema_editor): - login_acl_model = apps.get_model('acls', 'LoginACL') - - name_used = [] - login_acls = [] - for login_acl in login_acl_model.objects.all().select_related('user'): - name = '{}_{}'.format(login_acl.name, login_acl.user.username) - if name.lower() in name_used: - name += '_{}'.format(str(login_acl.user_id)[:4]) - name_used.append(name.lower()) - login_acl.name = name - login_acl.users = { - "type": "ids", "ids": [str(login_acl.user_id)] - } - login_acls.append(login_acl) - login_acl_model.objects.bulk_update(login_acls, ['name', 'users']) - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0015_connectmethodacl'), - ] - - operations = [ - migrations.AddField( - model_name='loginacl', - name='users', - field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'), - ), - migrations.RunPython(migrate_users_login_acls), - migrations.RemoveField( - model_name='loginacl', - name='user', - ), - migrations.AlterField( - model_name='loginacl', - name='name', - field=models.CharField(max_length=128, unique=True, verbose_name='Name'), - ), - ] diff --git a/apps/acls/migrations/0017_alter_connectmethodacl_options.py b/apps/acls/migrations/0017_alter_connectmethodacl_options.py deleted file mode 100644 index 6767771d6..000000000 --- a/apps/acls/migrations/0017_alter_connectmethodacl_options.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-13 07:49 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0016_auto_20230606_1857'), - ] - - operations = [ - migrations.AlterModelOptions( - name='connectmethodacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Connect method acl'}, - ), - ] diff --git a/apps/acls/migrations/0018_alter_commandfilteracl_command_groups.py b/apps/acls/migrations/0018_alter_commandfilteracl_command_groups.py deleted file mode 100644 index 0dea952a8..000000000 --- a/apps/acls/migrations/0018_alter_commandfilteracl_command_groups.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-18 10:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('acls', '0017_alter_connectmethodacl_options'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilteracl', - name='command_groups', - field=models.ManyToManyField(related_name='command_filters', to='acls.commandgroup', verbose_name='Command group'), - ), - ] diff --git a/apps/acls/models/command_acl.py b/apps/acls/models/command_acl.py index 2011cc60a..e04af69ee 100644 --- a/apps/acls/models/command_acl.py +++ b/apps/acls/models/command_acl.py @@ -23,7 +23,7 @@ class CommandGroup(JMSOrgBaseModel): max_length=16, default=TypeChoices.command, choices=TypeChoices.choices, verbose_name=_("Type") ) - content = models.TextField(verbose_name=_("Content"), help_text=_("One line one command")) + content = models.TextField(verbose_name=_("Content"), help_text=_("One command per line")) ignore_case = models.BooleanField(default=True, verbose_name=_('Ignore case')) TypeChoices = TypeChoices diff --git a/apps/acls/notifications.py b/apps/acls/notifications.py index b0e413590..0ad562127 100644 --- a/apps/acls/notifications.py +++ b/apps/acls/notifications.py @@ -39,7 +39,7 @@ class UserLoginReminderMsg(UserMessage): class AssetLoginReminderMsg(UserMessage): - subject = _('Asset login reminder') + subject = _('User login alert for asset') def __init__(self, user, asset: Asset, login_user: User, account: Account, input_username): self.asset = asset diff --git a/apps/acls/templates/acls/asset_login_reminder.html b/apps/acls/templates/acls/asset_login_reminder.html index 672c5e8de..4d31fc3fc 100644 --- a/apps/acls/templates/acls/asset_login_reminder.html +++ b/apps/acls/templates/acls/asset_login_reminder.html @@ -1,13 +1,16 @@ {% load i18n %} -

{% trans 'Respectful' %}: {{ recipient.name }}[{{ recipient.username }}]

+

{% trans 'Dear' %}: {{ recipient.name }}[{{ recipient.username }}]


-

{% trans 'User' %}: [{{ name }}({{ username }})]

-

{% trans 'Assets' %}: [{{ asset }}]

-

{% trans 'Account' %}: [{{ account_name }}({{ account }})]

+

{% trans 'We would like to inform you that a user has recently logged into the following asset:' %}

+

{% trans 'Asset details' %}:

+
-

{% trans 'The user has just logged in to the asset. Please ensure that this is an authorized operation. If you suspect that this is an unauthorized access, please take appropriate measures immediately.' %}

- -

{% trans 'Thank you' %}!

+

{% trans 'Please review the login activity to ensure the security and proper usage of the asset. If you did not authorize this login or if you notice any suspicious activity, please take the necessary actions immediately.' %}

+

{% trans 'Thank you for your attention to this matter' %}!

\ No newline at end of file diff --git a/apps/acls/templates/acls/user_login_reminder.html b/apps/acls/templates/acls/user_login_reminder.html index fe4c1d9a9..521d7d41a 100644 --- a/apps/acls/templates/acls/user_login_reminder.html +++ b/apps/acls/templates/acls/user_login_reminder.html @@ -1,14 +1,16 @@ {% load i18n %} -

{% trans 'Respectful' %}: {{ recipient.name }}[{{ recipient.username }}]

+

{% trans 'Dear' %}: {{ recipient.name }}[{{ recipient.username }}]


-

{% trans 'User' %}: [{{ username }}]

-

IP: [{{ ip }}]

-

{% trans 'Login city' %}: [{{ city }}]

-

{% trans 'User agent' %}: [{{ user_agent }}]

+

{% trans 'We would like to inform you that a user has recently logged:' %}

+

{% trans 'User details' %}:

+
-

{% trans 'The user has just successfully logged into the system. Please ensure that this is an authorized operation. If you suspect that this is an unauthorized access, please take appropriate measures immediately.' %}

- -

{% trans 'Thank you' %}!

- +

{% trans 'Please review the login activity to ensure the security and proper usage of the asset. If you did not authorize this login or if you notice any suspicious activity, please take the necessary actions immediately.' %}

+

{% trans 'Thank you for your attention to this matter' %}!

diff --git a/apps/applications/api/application.py b/apps/applications/api/application.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/applications/apps.py b/apps/applications/apps.py deleted file mode 100644 index c672bf36e..000000000 --- a/apps/applications/apps.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import unicode_literals - -from django.apps import AppConfig -from django.utils.translation import gettext_lazy as _ - - -class ApplicationsConfig(AppConfig): - name = 'applications' - verbose_name = _('Applications') - - def ready(self): - super().ready() diff --git a/apps/applications/migrations/0001_initial.py b/apps/applications/migrations/0001_initial.py deleted file mode 100644 index 26948fc73..000000000 --- a/apps/applications/migrations/0001_initial.py +++ /dev/null @@ -1,42 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-20 11:04 - -import common.db.fields -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('assets', '0026_auto_20190325_2035'), - ] - - operations = [ - migrations.CreateModel( - name='RemoteApp', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('Browser', (('chrome', 'Chrome'),)), ('Database tools', (('mysql_workbench', 'MySQL Workbench'),)), ('Virtualization tools', (('vmware_client', 'vSphere Client'),)), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type')), - ('path', models.CharField(max_length=128, verbose_name='App path')), - ('params', common.db.fields.EncryptJsonDictTextField(blank=True, default={}, max_length=4096, null=True, verbose_name='Parameters')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')), - ('system_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.SystemUser', verbose_name='System user')), - ], - options={ - 'verbose_name': 'RemoteApp', - 'ordering': ('name',), - }, - ), - migrations.AlterUniqueTogether( - name='remoteapp', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/applications/migrations/0002_remove_remoteapp_system_user.py b/apps/applications/migrations/0002_remove_remoteapp_system_user.py deleted file mode 100644 index 03b320752..000000000 --- a/apps/applications/migrations/0002_remove_remoteapp_system_user.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-09 09:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0001_initial'), - ('perms', '0009_remoteapppermission_system_users'), - ] - - operations = [ - migrations.RemoveField( - model_name='remoteapp', - name='system_user', - ), - ] diff --git a/apps/applications/migrations/0003_auto_20191210_1659.py b/apps/applications/migrations/0003_auto_20191210_1659.py deleted file mode 100644 index fc3e4cdf5..000000000 --- a/apps/applications/migrations/0003_auto_20191210_1659.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-10 08:59 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0002_remove_remoteapp_system_user'), - ] - - operations = [ - migrations.AlterField( - model_name='remoteapp', - name='type', - field=models.CharField(choices=[('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type'), - ), - ] diff --git a/apps/applications/migrations/0004_auto_20191218_1705.py b/apps/applications/migrations/0004_auto_20191218_1705.py deleted file mode 100644 index f22d2e290..000000000 --- a/apps/applications/migrations/0004_auto_20191218_1705.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-18 09:05 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0003_auto_20191210_1659'), - ] - - operations = [ - migrations.CreateModel( - name='DatabaseApp', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=128, verbose_name='Type')), - ('host', models.CharField(db_index=True, max_length=128, verbose_name='Host')), - ('port', models.IntegerField(default=3306, verbose_name='Port')), - ('database', models.CharField(blank=True, db_index=True, max_length=128, null=True, verbose_name='Database')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ], - options={ - 'verbose_name': 'DatabaseApp', - 'ordering': ('name',), - }, - ), - migrations.AlterUniqueTogether( - name='databaseapp', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/applications/migrations/0005_k8sapp.py b/apps/applications/migrations/0005_k8sapp.py deleted file mode 100644 index 3f6964a88..000000000 --- a/apps/applications/migrations/0005_k8sapp.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-07 07:13 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0004_auto_20191218_1705'), - ] - - operations = [ - migrations.CreateModel( - name='K8sApp', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('k8s', 'Kubernetes')], default='k8s', max_length=128, verbose_name='Type')), - ('cluster', models.CharField(max_length=1024, verbose_name='Cluster')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ], - options={ - 'verbose_name': 'KubernetesApp', - 'ordering': ('name',), - 'unique_together': {('org_id', 'name')}, - }, - ), - ] diff --git a/apps/applications/migrations/0006_application.py b/apps/applications/migrations/0006_application.py deleted file mode 100644 index 423e9468a..000000000 --- a/apps/applications/migrations/0006_application.py +++ /dev/null @@ -1,139 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-19 12:01 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -CATEGORY_DB_LIST = ['mysql', 'oracle', 'postgresql', 'mariadb'] -CATEGORY_REMOTE_LIST = ['chrome', 'mysql_workbench', 'vmware_client', 'custom'] -CATEGORY_CLOUD_LIST = ['k8s'] - -CATEGORY_DB = 'db' -CATEGORY_REMOTE = 'remote_app' -CATEGORY_CLOUD = 'cloud' -CATEGORY_LIST = [CATEGORY_DB, CATEGORY_REMOTE, CATEGORY_CLOUD] - - -def get_application_category(old_app): - _type = old_app.type - if _type in CATEGORY_DB_LIST: - category = CATEGORY_DB - elif _type in CATEGORY_REMOTE_LIST: - category = CATEGORY_REMOTE - elif _type in CATEGORY_CLOUD_LIST: - category = CATEGORY_CLOUD - else: - category = None - return category - - -def common_to_application_json(old_app): - category = get_application_category(old_app) - date_updated = old_app.date_updated if hasattr(old_app, 'date_updated') else old_app.date_created - return { - 'id': old_app.id, - 'name': old_app.name, - 'type': old_app.type, - 'category': category, - 'comment': old_app.comment, - 'created_by': old_app.created_by, - 'date_created': old_app.date_created, - 'date_updated': date_updated, - 'org_id': old_app.org_id - } - - -def db_to_application_json(database): - app_json = common_to_application_json(database) - app_json.update({ - 'attrs': { - 'host': database.host, - 'port': database.port, - 'database': database.database - } - }) - return app_json - - -def remote_to_application_json(remote): - app_json = common_to_application_json(remote) - attrs = { - 'asset': str(remote.asset.id), - 'path': remote.path, - } - attrs.update(remote.params) - app_json.update({ - 'attrs': attrs - }) - return app_json - - -def k8s_to_application_json(k8s): - app_json = common_to_application_json(k8s) - app_json.update({ - 'attrs': { - 'cluster': k8s.cluster - } - }) - return app_json - - -def migrate_and_integrate_applications(apps, schema_editor): - db_alias = schema_editor.connection.alias - - database_app_model = apps.get_model("applications", "DatabaseApp") - remote_app_model = apps.get_model("applications", "RemoteApp") - k8s_app_model = apps.get_model("applications", "K8sApp") - - database_apps = database_app_model.objects.using(db_alias).all() - remote_apps = remote_app_model.objects.using(db_alias).all() - k8s_apps = k8s_app_model.objects.using(db_alias).all() - - database_applications = [db_to_application_json(db_app) for db_app in database_apps] - remote_applications = [remote_to_application_json(remote_app) for remote_app in remote_apps] - k8s_applications = [k8s_to_application_json(k8s_app) for k8s_app in k8s_apps] - - applications_json = database_applications + remote_applications + k8s_applications - application_model = apps.get_model("applications", "Application") - applications = [ - application_model(**application_json) - for application_json in applications_json - if application_json['category'] in CATEGORY_LIST - ] - for application in applications: - if application_model.objects.using(db_alias).filter(name=application.name).exists(): - application.name = '{}-{}'.format(application.name, application.type) - application.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0057_fill_node_value_assets_amount_and_parent_key'), - ('applications', '0005_k8sapp'), - ] - - operations = [ - migrations.CreateModel( - name='Application', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('category', models.CharField(choices=[('db', 'Database'), ('remote_app', 'Remote app'), ('cloud', 'Cloud')], max_length=16, verbose_name='Category')), - ('type', models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type')), - ('attrs', models.JSONField(default=dict)), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ('domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='applications', to='assets.Domain', verbose_name='Domain')), - ], - options={ - 'ordering': ('name',), - 'unique_together': {('org_id', 'name')}, - }, - ), - migrations.RunPython(migrate_and_integrate_applications), - ] diff --git a/apps/applications/migrations/0007_auto_20201119_1110.py b/apps/applications/migrations/0007_auto_20201119_1110.py deleted file mode 100644 index e206f8404..000000000 --- a/apps/applications/migrations/0007_auto_20201119_1110.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2020-11-19 03:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0006_application'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='attrs', - field=models.JSONField(), - ), - ] diff --git a/apps/applications/migrations/0008_auto_20210104_0435.py b/apps/applications/migrations/0008_auto_20210104_0435.py deleted file mode 100644 index 2942ecf6e..000000000 --- a/apps/applications/migrations/0008_auto_20210104_0435.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.1 on 2021-01-03 20:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0017_auto_20210104_0435'), - ('applications', '0007_auto_20201119_1110'), - ] - - operations = [ - migrations.DeleteModel( - name='DatabaseApp', - ), - migrations.DeleteModel( - name='K8sApp', - ), - migrations.AlterField( - model_name='application', - name='attrs', - field=models.JSONField(default=dict, verbose_name='Attrs'), - ), - migrations.DeleteModel( - name='RemoteApp', - ), - ] diff --git a/apps/applications/migrations/0009_applicationuser.py b/apps/applications/migrations/0009_applicationuser.py deleted file mode 100644 index 7b3368ef9..000000000 --- a/apps/applications/migrations/0009_applicationuser.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-23 09:48 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0070_auto_20210426_1515'), - ('applications', '0008_auto_20210104_0435'), - ] - - operations = [ - migrations.CreateModel( - name='ApplicationUser', - fields=[ - ], - options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.systemuser',), - ), - ] diff --git a/apps/applications/migrations/0010_appaccount_historicalappaccount.py b/apps/applications/migrations/0010_appaccount_historicalappaccount.py deleted file mode 100644 index 515754f32..000000000 --- a/apps/applications/migrations/0010_appaccount_historicalappaccount.py +++ /dev/null @@ -1,96 +0,0 @@ -# Generated by Django 3.1.12 on 2021-08-26 09:07 - -import uuid - -import django.core.validators -import django.db.models.deletion -import simple_history.models -from django.conf import settings -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0076_delete_assetuser'), - ('applications', '0009_applicationuser'), - ] - - operations = [ - migrations.CreateModel( - name='HistoricalAccount', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[ - django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], - verbose_name='Username')), - ('password', - common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('private_key', - common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')), - ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('date_created', models.DateTimeField(blank=True, editable=False, verbose_name='Date created')), - ('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField()), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', - models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('app', models.ForeignKey(blank=True, db_constraint=False, null=True, - on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', - to='applications.application', verbose_name='Database')), - ('history_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL)), - ('systemuser', models.ForeignKey(blank=True, db_constraint=False, null=True, - on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', - to='assets.systemuser', verbose_name='System user')), - ], - options={ - 'verbose_name': 'historical Account', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': 'history_date', - }, - bases=(simple_history.models.HistoricalChanges, models.Model), - ), - migrations.CreateModel( - name='Account', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[ - django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], - verbose_name='Username')), - ('password', - common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('private_key', - common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')), - ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('app', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, - to='applications.application', verbose_name='Database')), - ('systemuser', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.systemuser', - verbose_name='System user')), - ], - options={ - 'verbose_name': 'Account', - 'unique_together': {('username', 'app', 'systemuser')}, - }, - bases=(models.Model,), - ), - ] diff --git a/apps/applications/migrations/0011_auto_20210826_1759.py b/apps/applications/migrations/0011_auto_20210826_1759.py deleted file mode 100644 index 937102c07..000000000 --- a/apps/applications/migrations/0011_auto_20210826_1759.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 3.1.12 on 2021-08-26 09:59 - -from django.db import migrations, transaction -from django.db.models import F - - -def migrate_app_account(apps, schema_editor): - db_alias = schema_editor.connection.alias - app_perm_model = apps.get_model("perms", "ApplicationPermission") - app_account_model = apps.get_model("applications", 'Account') - - queryset = app_perm_model.objects \ - .exclude(system_users__isnull=True) \ - .exclude(applications__isnull=True) \ - .annotate(systemuser=F('system_users')) \ - .annotate(app=F('applications')) \ - .values('app', 'systemuser', 'org_id') - - accounts = [] - for p in queryset: - if not p['app']: - continue - account = app_account_model( - app_id=p['app'], systemuser_id=p['systemuser'], - version=1, org_id=p['org_id'] - ) - accounts.append(account) - - app_account_model.objects.using(db_alias).bulk_create(accounts, ignore_conflicts=True) - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0010_appaccount_historicalappaccount'), - ] - - operations = [ - migrations.RunPython(migrate_app_account) - ] diff --git a/apps/applications/migrations/0012_auto_20211014_2209.py b/apps/applications/migrations/0012_auto_20211014_2209.py deleted file mode 100644 index 3375f7399..000000000 --- a/apps/applications/migrations/0012_auto_20211014_2209.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.13 on 2021-10-14 14:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0011_auto_20210826_1759'), - ] - - operations = [ - migrations.AlterField( - model_name='account', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='historicalaccount', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/applications/migrations/0013_auto_20211026_1711.py b/apps/applications/migrations/0013_auto_20211026_1711.py deleted file mode 100644 index 28d80cdbc..000000000 --- a/apps/applications/migrations/0013_auto_20211026_1711.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.13 on 2021-10-26 09:11 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0012_auto_20211014_2209'), - ] - - operations = [ - migrations.AlterModelOptions( - name='application', - options={'ordering': ('name',), 'verbose_name': 'Application'}, - ), - ] diff --git a/apps/applications/migrations/0014_auto_20211105_1605.py b/apps/applications/migrations/0014_auto_20211105_1605.py deleted file mode 100644 index ab0063c3c..000000000 --- a/apps/applications/migrations/0014_auto_20211105_1605.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-05 08:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0013_auto_20211026_1711'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0015_auto_20220112_2035.py b/apps/applications/migrations/0015_auto_20220112_2035.py deleted file mode 100644 index 3f91878df..000000000 --- a/apps/applications/migrations/0015_auto_20220112_2035.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-12 12:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0014_auto_20211105_1605'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('redis', 'Redis'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0016_auto_20220118_1455.py b/apps/applications/migrations/0016_auto_20220118_1455.py deleted file mode 100644 index edb97bade..000000000 --- a/apps/applications/migrations/0016_auto_20220118_1455.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-18 06:55 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0015_auto_20220112_2035'), - ] - - operations = [ - migrations.AlterField( - model_name='account', - name='app', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='applications.application', verbose_name='Application'), - ), - migrations.AlterField( - model_name='historicalaccount', - name='app', - field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='applications.application', verbose_name='Application'), - ), - ] diff --git a/apps/applications/migrations/0017_auto_20220217_2135.py b/apps/applications/migrations/0017_auto_20220217_2135.py deleted file mode 100644 index fd6bbeaa8..000000000 --- a/apps/applications/migrations/0017_auto_20220217_2135.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0016_auto_20220118_1455'), - ] - - operations = [ - migrations.AlterModelOptions( - name='account', - options={'permissions': [('view_applicationaccountsecret', 'Can view application account secret'), ('change_appplicationaccountsecret', 'Can change application account secret')], 'verbose_name': 'Application account'}, - ), - migrations.AlterModelOptions( - name='applicationuser', - options={'verbose_name': 'Application user'}, - ), - migrations.AlterModelOptions( - name='historicalaccount', - options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Application account'}, - ), - ] diff --git a/apps/applications/migrations/0018_auto_20220223_1539.py b/apps/applications/migrations/0018_auto_20220223_1539.py deleted file mode 100644 index 637d8cb86..000000000 --- a/apps/applications/migrations/0018_auto_20220223_1539.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-23 07:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0017_auto_20220217_2135'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0019_auto_20220310_1853.py b/apps/applications/migrations/0019_auto_20220310_1853.py deleted file mode 100644 index 42a5683a0..000000000 --- a/apps/applications/migrations/0019_auto_20220310_1853.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-10 10:53 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0018_auto_20220223_1539'), - ] - - operations = [ - migrations.AlterModelOptions( - name='application', - options={'ordering': ('name',), 'permissions': [('match_application', 'Can match application')], 'verbose_name': 'Application'}, - ), - ] diff --git a/apps/applications/migrations/0020_auto_20220316_2028.py b/apps/applications/migrations/0020_auto_20220316_2028.py deleted file mode 100644 index 3eeedf2d6..000000000 --- a/apps/applications/migrations/0020_auto_20220316_2028.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-16 12:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0019_auto_20220310_1853'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0021_auto_20220629_1826.py b/apps/applications/migrations/0021_auto_20220629_1826.py deleted file mode 100644 index b74977b7d..000000000 --- a/apps/applications/migrations/0021_auto_20220629_1826.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-29 10:26 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0020_auto_20220316_2028'), - ] - - operations = [ - migrations.AlterModelOptions( - name='historicalaccount', - options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Application account', 'verbose_name_plural': 'historical Application accounts'}, - ), - migrations.AlterField( - model_name='historicalaccount', - name='history_date', - field=models.DateTimeField(db_index=True), - ), - ] diff --git a/apps/applications/migrations/0022_auto_20220714_1046.py b/apps/applications/migrations/0022_auto_20220714_1046.py deleted file mode 100644 index f7475a8c3..000000000 --- a/apps/applications/migrations/0022_auto_20220714_1046.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-14 02:46 - -from django.db import migrations - - -def migrate_db_oracle_version_to_attrs(apps, schema_editor): - db_alias = schema_editor.connection.alias - model = apps.get_model("applications", "Application") - oracles = list(model.objects.using(db_alias).filter(type='oracle')) - for o in oracles: - o.attrs['version'] = '12c' - model.objects.using(db_alias).bulk_update(oracles, ['attrs']) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0021_auto_20220629_1826'), - ] - - operations = [ - migrations.RunPython(migrate_db_oracle_version_to_attrs) - ] diff --git a/apps/applications/migrations/0023_auto_20220715_1556.py b/apps/applications/migrations/0023_auto_20220715_1556.py deleted file mode 100644 index bc6e20770..000000000 --- a/apps/applications/migrations/0023_auto_20220715_1556.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 3.1.14 on 2022-07-15 07:56 -import time - -from django.db import migrations - - -def migrate_account_dirty_data(apps, schema_editor): - db_alias = schema_editor.connection.alias - account_model = apps.get_model('applications', 'Account') - - count = 0 - bulk_size = 1000 - - while True: - accounts = account_model.objects.using(db_alias) \ - .filter(org_id='')[count:count + bulk_size] - - if not accounts: - break - - accounts = list(accounts) - start = time.time() - for i in accounts: - if i.app: - org_id = i.app.org_id - elif i.systemuser: - org_id = i.systemuser.org_id - else: - org_id = '' - if org_id: - i.org_id = org_id - - account_model.objects.bulk_update(accounts, ['org_id', ]) - print("Update account org is empty: {}-{} using: {:.2f}s".format( - count, count + len(accounts), time.time() - start - )) - count += len(accounts) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0022_auto_20220714_1046'), - ] - - operations = [ - migrations.RunPython(migrate_account_dirty_data), - ] diff --git a/apps/applications/migrations/0024_alter_application_type.py b/apps/applications/migrations/0024_alter_application_type.py deleted file mode 100644 index 4f26e0905..000000000 --- a/apps/applications/migrations/0024_alter_application_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-04 07:06 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0023_auto_20220715_1556'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('clickhouse', 'ClickHouse'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0025_auto_20220817_1346.py b/apps/applications/migrations/0025_auto_20220817_1346.py deleted file mode 100644 index a1a7da6ea..000000000 --- a/apps/applications/migrations/0025_auto_20220817_1346.py +++ /dev/null @@ -1,60 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 05:46 - -from django.db import migrations, models - - -def migrate_db_oracle_version_to_attrs(apps, schema_editor): - db_alias = schema_editor.connection.alias - model = apps.get_model("applications", "Application") - oracles = list(model.objects.using(db_alias).filter(type='oracle')) - for o in oracles: - o.attrs['version'] = '12c' - model.objects.using(db_alias).bulk_update(oracles, ['attrs']) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0024_alter_application_type'), - ] - - operations = [ - migrations.RunPython(migrate_db_oracle_version_to_attrs), - migrations.AlterUniqueTogether( - name='account', - unique_together=None, - ), - migrations.RemoveField( - model_name='account', - name='app', - ), - migrations.RemoveField( - model_name='account', - name='systemuser', - ), - migrations.RemoveField( - model_name='application', - name='domain', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='app', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='history_user', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='systemuser', - ), - migrations.AlterField( - model_name='application', - name='category', - field=models.CharField(max_length=16, verbose_name='Category'), - ), - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0026_auto_20220817_1716.py b/apps/applications/migrations/0026_auto_20220817_1716.py deleted file mode 100644 index bb9df0808..000000000 --- a/apps/applications/migrations/0026_auto_20220817_1716.py +++ /dev/null @@ -1,60 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 09:16 -import time - -from django.db import migrations - - -def migrate_account_dirty_data(apps, schema_editor): - db_alias = schema_editor.connection.alias - account_model = apps.get_model('applications', 'Account') - - count = 0 - bulk_size = 1000 - - while True: - accounts = account_model.objects.using(db_alias) \ - .filter(org_id='')[count:count + bulk_size] - - if not accounts: - break - - accounts = list(accounts) - start = time.time() - for i in accounts: - if i.app: - org_id = i.app.org_id - elif i.systemuser: - org_id = i.systemuser.org_id - else: - org_id = '' - if org_id: - i.org_id = org_id - - account_model.objects.bulk_update(accounts, ['org_id', ]) - print("Update account org is empty: {}-{} using: {:.2f}s".format( - count, count + len(accounts), time.time() - start - )) - count += len(accounts) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0025_auto_20220817_1346'), - ('perms', '0031_auto_20220816_1600'), - ('ops', '0022_auto_20220817_1346'), - ('assets', '0100_auto_20220711_1413'), - ('tickets', '0020_auto_20220817_1346'), - ] - - operations = [ - migrations.RunPython(migrate_account_dirty_data), - migrations.DeleteModel( - name='Account', - ), - migrations.DeleteModel( - name='HistoricalAccount', - ), - migrations.DeleteModel( - name='ApplicationUser', - ), - ] diff --git a/apps/applications/migrations/0027_auto_20221220_1956.py b/apps/applications/migrations/0027_auto_20221220_1956.py deleted file mode 100644 index a72162974..000000000 --- a/apps/applications/migrations/0027_auto_20221220_1956.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0026_auto_20220817_1716'), - ] - - operations = [ - migrations.AddField( - model_name='application', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='application', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='application', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/applications/migrations/__init__.py b/apps/applications/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/applications/models.py b/apps/applications/models.py deleted file mode 100644 index c13ddc092..000000000 --- a/apps/applications/models.py +++ /dev/null @@ -1,24 +0,0 @@ -from django.db import models -from django.utils.translation import gettext_lazy as _ - -from common.db.models import JMSBaseModel -from orgs.mixins.models import OrgModelMixin - - -class Application(JMSBaseModel, OrgModelMixin): - name = models.CharField(max_length=128, verbose_name=_('Name')) - category = models.CharField( - max_length=16, verbose_name=_('Category') - ) - type = models.CharField( - max_length=16, verbose_name=_('Type') - ) - attrs = models.JSONField(default=dict, verbose_name=_('Attrs')) - - class Meta: - verbose_name = _('Application') - unique_together = [('org_id', 'name')] - ordering = ('name',) - permissions = [ - ('match_application', _('Can match application')), - ] diff --git a/apps/applications/signal_handlers.py b/apps/applications/signal_handlers.py deleted file mode 100644 index 4aa11c79b..000000000 --- a/apps/applications/signal_handlers.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -# \ No newline at end of file diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index f7e088319..09160b9e6 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -3,6 +3,7 @@ from collections import defaultdict import django_filters +from django.conf import settings from django.shortcuts import get_object_or_404 from django.utils.translation import gettext as _ from rest_framework import status @@ -179,6 +180,11 @@ class AssetViewSet(SuggestionMixin, OrgBulkModelViewSet): if request.path.find('/api/v1/assets/assets/') > -1: error = _('Cannot create asset directly, you should create a host or other') return Response({'error': error}, status=400) + + if not settings.XPACK_LICENSE_IS_VALID and self.model.objects.order_by().count() >= 5000: + error = _('The number of assets exceeds the limit of 5000') + return Response({'error': error}, status=400) + return super().create(request, *args, **kwargs) def filter_bulk_update_data(self): diff --git a/apps/assets/apps.py b/apps/assets/apps.py index 9ebd7a93d..74260a689 100644 --- a/apps/assets/apps.py +++ b/apps/assets/apps.py @@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _ class AssetsConfig(AppConfig): name = 'assets' - verbose_name = _('App assets') + verbose_name = _('App Assets') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py index 909ca5638..16be2068c 100644 --- a/apps/assets/automations/base/manager.py +++ b/apps/assets/automations/base/manager.py @@ -37,7 +37,7 @@ class SSHTunnelManager: info = self.file_to_json(runner.inventory) servers, not_valid = [], [] for k, host in info['all']['hosts'].items(): - jms_asset, jms_gateway = host.get('jms_asset'), host.get('gateway') + jms_asset, jms_gateway = host.get('jms_asset'), host.get('jms_gateway') if not jms_gateway: continue try: @@ -324,19 +324,19 @@ class BasePlaybookManager: shutil.rmtree(self.runtime_dir, ignore_errors=True) def run(self, *args, **kwargs): - print(">>> 任务准备阶段\n") + print(_(">>> Task preparation phase"), end="\n") runners = self.get_runners() if len(runners) > 1: - print("### 分次执行任务, 总共 {}\n".format(len(runners))) + print(_(">>> Executing tasks in batches, total {runner_count}").format(runner_count=len(runners))) elif len(runners) == 1: - print(">>> 开始执行任务\n") + print(_(">>> Start executing tasks")) else: - print("### 没有需要执行的任务\n") + print(_(">>> No tasks need to be executed"), end="\n") self.execution.date_start = timezone.now() for i, runner in enumerate(runners, start=1): if len(runners) > 1: - print(">>> 开始执行第 {} 批任务".format(i)) + print(_(">>> Begin executing batch {index} of tasks").format(index=i)) ssh_tunnel = SSHTunnelManager() ssh_tunnel.local_gateway_prepare(runner) try: diff --git a/apps/assets/automations/ping/custom/ssh/main.yml b/apps/assets/automations/ping/custom/ssh/main.yml index d40a7a4e8..89b92bcaa 100644 --- a/apps/assets/automations/ping/custom/ssh/main.yml +++ b/apps/assets/automations/ping/custom/ssh/main.yml @@ -14,11 +14,11 @@ login_port: "{{ jms_asset.port }}" login_secret_type: "{{ jms_account.secret_type }}" login_private_key_path: "{{ jms_account.private_key_path }}" - become: "{{ custom_become | default(False) }}" - become_method: "{{ custom_become_method | default('su') }}" - become_user: "{{ custom_become_user | default('') }}" - become_password: "{{ custom_become_password | default('') }}" - become_private_key_path: "{{ custom_become_private_key_path | default(None) }}" + become: "{{ jms_custom_become | default(False) }}" + become_method: "{{ jms_custom_become_method | default('su') }}" + become_user: "{{ jms_custom_become_user | default('') }}" + become_password: "{{ jms_custom_become_password | default('') }}" + become_private_key_path: "{{ jms_custom_become_private_key_path | default(None) }}" old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}" gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" diff --git a/apps/assets/const/automation.py b/apps/assets/const/automation.py index 4a2054db1..135102312 100644 --- a/apps/assets/const/automation.py +++ b/apps/assets/const/automation.py @@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _ class Connectivity(TextChoices): UNKNOWN = '-', _('Unknown') - OK = 'ok', _('Ok') + OK = 'ok', _('OK') ERR = 'err', _('Error') diff --git a/apps/assets/const/base.py b/apps/assets/const/base.py index c318115b5..3236050ea 100644 --- a/apps/assets/const/base.py +++ b/apps/assets/const/base.py @@ -113,8 +113,7 @@ class BaseType(TextChoices): @classmethod def get_choices(cls): if not settings.XPACK_ENABLED: - return [ - (tp.value, tp.label) - for tp in cls.get_community_types() - ] - return cls.choices + choices = [(tp.value, tp.label) for tp in cls.get_community_types()] + else: + choices = cls.choices + return choices diff --git a/apps/assets/const/category.py b/apps/assets/const/category.py index 9ccbb134e..8c4d387d8 100644 --- a/apps/assets/const/category.py +++ b/apps/assets/const/category.py @@ -12,7 +12,6 @@ class Category(ChoicesMixin, models.TextChoices): DATABASE = 'database', _("Database") CLOUD = 'cloud', _("Cloud service") WEB = 'web', _("Web") - GPT = 'gpt', "GPT" CUSTOM = 'custom', _("Custom type") @classmethod diff --git a/apps/assets/const/database.py b/apps/assets/const/database.py index 6802ed3b4..6dcd42447 100644 --- a/apps/assets/const/database.py +++ b/apps/assets/const/database.py @@ -37,6 +37,7 @@ class DatabaseTypes(BaseType): 'verify_account_enabled': True, 'change_secret_enabled': True, 'push_account_enabled': True, + 'remove_account_enabled': True, }, cls.REDIS: { 'ansible_enabled': False, diff --git a/apps/assets/const/device.py b/apps/assets/const/device.py index bdf4502e0..212b18b99 100644 --- a/apps/assets/const/device.py +++ b/apps/assets/const/device.py @@ -42,7 +42,8 @@ class DeviceTypes(BaseType): 'gather_accounts_enabled': False, 'verify_account_enabled': True, 'change_secret_enabled': True, - 'push_account_enabled': False + 'push_account_enabled': False, + 'remove_account_enabled': False, } } diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py index be8f1d1bf..f408e5e5e 100644 --- a/apps/assets/const/host.py +++ b/apps/assets/const/host.py @@ -53,7 +53,9 @@ class HostTypes(BaseType): 'gather_accounts_enabled': True, 'verify_account_enabled': True, 'change_secret_enabled': True, - 'push_account_enabled': True + 'push_account_enabled': True, + 'remove_account_enabled': True, + }, cls.WINDOWS: { 'ansible_config': { diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 53f41c218..b03f22d12 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -166,23 +166,26 @@ class AllTypes(ChoicesMixin): @classmethod def category_types(cls): - return ( + types = [ (Category.HOST, HostTypes), (Category.DEVICE, DeviceTypes), (Category.DATABASE, DatabaseTypes), - (Category.CLOUD, CloudTypes), (Category.WEB, WebTypes), - (Category.GPT, GPTTypes), - (Category.CUSTOM, CustomTypes), - ) + ] + if settings.XPACK_ENABLED: + types.extend([ + (Category.CLOUD, CloudTypes), + (Category.CUSTOM, CustomTypes), + ]) + return types @classmethod def get_types(cls, exclude_custom=False): choices = [] for name, tp in dict(cls.category_types()).items(): - if name == Category.CUSTOM and exclude_custom: - continue + # if name == Category.CUSTOM and exclude_custom: + # continue choices.extend(tp.get_types()) return choices @@ -331,11 +334,13 @@ class AllTypes(ChoicesMixin): return data @classmethod - def create_or_update_by_platform_data(cls, platform_data, platform_cls=None): + def create_or_update_by_platform_data(cls, platform_data, platform_cls=None, automation_cls=None): # 不直接用 Platform 是因为可能在 migrations 中使用 - from assets.models import Platform + from assets.models import Platform, PlatformAutomation if platform_cls is None: platform_cls = Platform + if automation_cls is None: + automation_cls = PlatformAutomation automation_data = platform_data.pop('automation', {}) protocols_data = platform_data.pop('protocols', []) @@ -344,12 +349,18 @@ class AllTypes(ChoicesMixin): platform, created = platform_cls.objects.update_or_create( defaults=platform_data, name=name ) - if not platform.automation: - automation = platform_cls.automation.field.related_model.objects.create() + + try: + automation = platform.automation + except: + automation = None + + if not automation: + automation = automation_cls.objects.create() platform.automation = automation platform.save() else: - automation = platform.automation + automation = automation for k, v in automation_data.items(): setattr(automation, k, v) automation.save() diff --git a/apps/assets/migrations/0001_initial.py b/apps/assets/migrations/0001_initial.py index 03c945c57..1efb07ebb 100644 --- a/apps/assets/migrations/0001_initial.py +++ b/apps/assets/migrations/0001_initial.py @@ -1,19 +1,13 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-21 16:06 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import assets.models.utils -from django.db import migrations, models -import django.db.models.deletion import uuid +import django.db.models.deletion +from django.db import migrations, models -def add_default_group(apps, schema_editor): - group_model = apps.get_model("assets", "AssetGroup") - db_alias = schema_editor.connection.alias - group_model.objects.using(db_alias).create( - name="Default" - ) +import assets.models.asset.common +import assets.models.node +import common.db.fields class Migration(migrations.Migration): @@ -24,136 +18,306 @@ class Migration(migrations.Migration): ] operations = [ - migrations.CreateModel( - name='AdminUser', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(max_length=16, verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=32, null=True, verbose_name='Created by')), - ('become', models.BooleanField(default=True)), - ('become_method', models.CharField(choices=[('sudo', 'sudo'), ('su', 'su')], default='sudo', max_length=4)), - ('become_user', models.CharField(default='root', max_length=64)), - ('_become_pass', models.CharField(default='', max_length=128)), - ], - options={ - 'ordering': ['name'], - }, - ), migrations.CreateModel( name='Asset', fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('ip', models.GenericIPAddressField(db_index=True, verbose_name='IP')), - ('hostname', models.CharField(max_length=128, unique=True, verbose_name='Hostname')), - ('port', models.IntegerField(default=22, verbose_name='Port')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'OK'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), + ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('address', models.CharField(db_index=True, max_length=767, verbose_name='Address')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('gathered_info', models.JSONField(blank=True, default=dict, verbose_name='Gathered info')), + ('custom_info', models.JSONField(default=dict, verbose_name='Custom info')), + ], + options={ + 'verbose_name': 'Asset', + 'ordering': [], + 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('match_asset', 'Can match asset'), ('change_assetnodes', 'Can change asset nodes')], + }, + bases=(assets.models.asset.common.NodesRelationMixin, assets.models.asset.common.JSONFilterMixin, models.Model), + ), + migrations.CreateModel( + name='AutomationExecution', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), + ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), + ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), + ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), + ('snapshot', common.db.fields.EncryptJsonDictTextField(blank=True, default=dict, null=True, verbose_name='Automation snapshot')), + ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), + ], + options={ + 'verbose_name': 'Automation task execution', + 'ordering': ('org_id', '-date_start'), + }, + ), + migrations.CreateModel( + name='BaseAutomation', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), + ('accounts', models.JSONField(default=list, verbose_name='Accounts')), + ('type', models.CharField(max_length=16, verbose_name='Type')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('type', models.CharField(blank=True, choices=[('Server', 'Server'), ('VM', 'VM'), ('Switch', 'Switch'), ('Router', 'Router'), ('Firewall', 'Firewall'), ('Storage', 'Storage')], default='Server', max_length=16, null=True, verbose_name='Asset type')), - ('env', models.CharField(blank=True, choices=[('Prod', 'Production'), ('Dev', 'Development'), ('Test', 'Testing')], default='Prod', max_length=8, null=True, verbose_name='Asset environment')), - ('status', models.CharField(blank=True, choices=[('In use', 'In use'), ('Out of use', 'Out of use')], default='In use', max_length=12, null=True, verbose_name='Asset status')), - ('public_ip', models.GenericIPAddressField(blank=True, null=True, verbose_name='Public IP')), - ('remote_card_ip', models.CharField(blank=True, max_length=16, null=True, verbose_name='Remote control card IP')), - ('cabinet_no', models.CharField(blank=True, max_length=32, null=True, verbose_name='Cabinet number')), - ('cabinet_pos', models.IntegerField(blank=True, null=True, verbose_name='Cabinet position')), - ('number', models.CharField(blank=True, max_length=32, null=True, verbose_name='Asset number')), - ('vendor', models.CharField(blank=True, max_length=64, null=True, verbose_name='Vendor')), - ('model', models.CharField(blank=True, max_length=54, null=True, verbose_name='Model')), - ('sn', models.CharField(blank=True, max_length=128, null=True, verbose_name='Serial number')), - ('cpu_model', models.CharField(blank=True, max_length=64, null=True, verbose_name='CPU model')), - ('cpu_count', models.IntegerField(null=True, verbose_name='CPU count')), - ('cpu_cores', models.IntegerField(null=True, verbose_name='CPU cores')), - ('memory', models.CharField(blank=True, max_length=64, null=True, verbose_name='Memory')), - ('disk_total', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk total')), - ('disk_info', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk info')), - ('platform', models.CharField(blank=True, max_length=128, null=True, verbose_name='Platform')), - ('os', models.CharField(blank=True, max_length=128, null=True, verbose_name='OS')), - ('os_version', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS version')), - ('os_arch', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS arch')), - ('hostname_raw', models.CharField(blank=True, max_length=128, null=True, verbose_name='Hostname raw')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ('admin_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')), - ], - ), - migrations.CreateModel( - name='AssetGroup', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=64, unique=True, verbose_name='Name')), - ('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('params', models.JSONField(default=dict, verbose_name='Parameters')), ], options={ - 'ordering': ['name'], + 'verbose_name': 'Automation task', }, ), migrations.CreateModel( - name='Cluster', + name='Domain', fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ], + options={ + 'verbose_name': 'Zone', + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='Node', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('key', models.CharField(max_length=64, unique=True, verbose_name='Key')), + ('value', models.CharField(max_length=128, verbose_name='Value')), + ('full_value', models.CharField(default='', max_length=4096, verbose_name='Full value')), + ('child_mark', models.IntegerField(default=0)), + ('date_create', models.DateTimeField(auto_now_add=True)), + ('parent_key', models.CharField(db_index=True, default='', max_length=64, verbose_name='Parent key')), + ('assets_amount', models.IntegerField(default=0)), + ], + options={ + 'verbose_name': 'Node', + 'ordering': ['parent_key', 'value'], + 'permissions': [('match_node', 'Can match node')], + }, + bases=(models.Model, assets.models.node.SomeNodesMixin, assets.models.node.FamilyMixin, assets.models.node.NodeAssetsMixin), + ), + migrations.CreateModel( + name='Platform', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('name', models.SlugField(allow_unicode=True, unique=True, verbose_name='Name')), + ('category', models.CharField(default='host', max_length=32, verbose_name='Category')), + ('type', models.CharField(default='linux', max_length=32, verbose_name='Type')), + ('meta', common.db.fields.JsonDictTextField(blank=True, null=True, verbose_name='Meta')), + ('internal', models.BooleanField(default=False, verbose_name='Internal')), + ('charset', models.CharField(choices=[('utf-8', 'UTF-8'), ('gbk', 'GBK')], default='utf-8', max_length=8, verbose_name='Charset')), + ('domain_enabled', models.BooleanField(default=True, verbose_name='Gateway enabled')), + ('su_enabled', models.BooleanField(default=False, verbose_name='Su enabled')), + ('su_method', models.CharField(blank=True, max_length=32, null=True, verbose_name='Su method')), + ('custom_fields', models.JSONField(default=list, null=True, verbose_name='Custom fields')), + ], + options={ + 'verbose_name': 'Platform', + }, + ), + migrations.CreateModel( + name='Cloud', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Cloud', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Custom', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Custom asset', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Database', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ('db_name', models.CharField(blank=True, max_length=1024, verbose_name='Database')), + ('use_ssl', models.BooleanField(default=False, verbose_name='Use SSL')), + ('ca_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='CA cert')), + ('client_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='Client cert')), + ('client_key', common.db.fields.EncryptTextField(blank=True, verbose_name='Client key')), + ('allow_invalid_cert', models.BooleanField(default=False, verbose_name='Allow invalid cert')), + ], + options={ + 'verbose_name': 'Database', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Device', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Device', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='GPT', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ('proxy', models.CharField(blank=True, default='', max_length=128, verbose_name='Proxy')), + ], + options={ + 'verbose_name': 'Web', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Host', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Host', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Web', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ('autofill', models.CharField(choices=[('no', 'Disabled'), ('basic', 'Basic'), ('script', 'Script')], default='basic', max_length=16, verbose_name='Autofill')), + ('username_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')), + ('password_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')), + ('submit_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')), + ('script', models.JSONField(blank=True, default=list, verbose_name='Script')), + ], + options={ + 'verbose_name': 'Web', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Protocol', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=32, verbose_name='Name')), - ('bandwidth', models.CharField(blank=True, max_length=32, verbose_name='Bandwidth')), - ('contact', models.CharField(blank=True, max_length=128, verbose_name='Contact')), - ('phone', models.CharField(blank=True, max_length=32, verbose_name='Phone')), - ('address', models.CharField(blank=True, max_length=128, verbose_name='Address')), - ('intranet', models.TextField(blank=True, verbose_name='Intranet')), - ('extranet', models.TextField(blank=True, verbose_name='Extranet')), + ('port', models.IntegerField(verbose_name='Port')), + ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='protocols', to='assets.asset', verbose_name='Asset')), + ], + ), + migrations.CreateModel( + name='PlatformProtocol', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=32, verbose_name='Name')), + ('port', models.IntegerField(verbose_name='Port')), + ('primary', models.BooleanField(default=False, verbose_name='Primary')), + ('required', models.BooleanField(default=False, verbose_name='Required')), + ('default', models.BooleanField(default=False, verbose_name='Default')), + ('public', models.BooleanField(default=True, verbose_name='Public')), + ('setting', models.JSONField(default=dict, verbose_name='Setting')), + ('platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='protocols', to='assets.platform')), + ], + ), + migrations.CreateModel( + name='PlatformAutomation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ansible_enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('ansible_config', models.JSONField(default=dict, verbose_name='Ansible config')), + ('ping_enabled', models.BooleanField(default=False, verbose_name='Ping enabled')), + ('ping_method', models.CharField(blank=True, max_length=32, null=True, verbose_name='Ping method')), + ('ping_params', models.JSONField(default=dict, verbose_name='Ping params')), + ('gather_facts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), + ('gather_facts_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), + ('gather_facts_params', models.JSONField(default=dict, verbose_name='Gather facts params')), + ('change_secret_enabled', models.BooleanField(default=False, verbose_name='Change secret enabled')), + ('change_secret_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Change secret method')), + ('change_secret_params', models.JSONField(default=dict, verbose_name='Change secret params')), + ('push_account_enabled', models.BooleanField(default=False, verbose_name='Push account enabled')), + ('push_account_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Push account method')), + ('push_account_params', models.JSONField(default=dict, verbose_name='Push account params')), + ('verify_account_enabled', models.BooleanField(default=False, verbose_name='Verify account enabled')), + ('verify_account_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Verify account method')), + ('verify_account_params', models.JSONField(default=dict, verbose_name='Verify account params')), + ('gather_accounts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), + ('gather_accounts_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), + ('gather_accounts_params', models.JSONField(default=dict, verbose_name='Gather facts params')), + ('remove_account_enabled', models.BooleanField(default=False, verbose_name='Remove account enabled')), + ('remove_account_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Remove account method')), + ('remove_account_params', models.JSONField(default=dict, verbose_name='Remove account params')), + ('platform', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automation', to='assets.platform')), + ], + ), + migrations.CreateModel( + name='Label', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('operator', models.CharField(blank=True, max_length=32, verbose_name='Operator')), - ('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('admin_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('value', models.CharField(max_length=128, verbose_name='Value')), + ('category', models.CharField(choices=[('S', 'System'), ('U', 'User')], default='U', max_length=128, verbose_name='Category')), + ('is_active', models.BooleanField(default=True, verbose_name='Is active')), ], options={ - 'ordering': ['name'], + 'verbose_name': 'Label', + 'db_table': 'assets_label', + 'unique_together': {('name', 'value', 'org_id')}, }, ), migrations.CreateModel( - name='SystemUser', + name='FavoriteAsset', fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(max_length=16, verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=32, null=True, verbose_name='Created by')), - ('priority', models.IntegerField(default=10, verbose_name='Priority')), - ('protocol', models.CharField(choices=[('ssh', 'ssh')], default='ssh', max_length=16, verbose_name='Protocol')), - ('auto_push', models.BooleanField(default=True, verbose_name='Auto push')), - ('sudo', models.TextField(default='/sbin/ifconfig', verbose_name='Sudo')), - ('shell', models.CharField(default='/bin/bash', max_length=64, verbose_name='Shell')), - ('cluster', models.ManyToManyField(blank=True, to='assets.Cluster', verbose_name='Cluster')), + ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset')), ], options={ - 'ordering': ['name'], + 'verbose_name': 'Favorite asset', }, ), - migrations.AddField( - model_name='asset', - name='cluster', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.Cluster', verbose_name='Cluster'), - ), - migrations.AddField( - model_name='asset', - name='groups', - field=models.ManyToManyField(blank=True, related_name='assets', to='assets.AssetGroup', verbose_name='Asset groups'), - ), - migrations.AlterUniqueTogether( - name='asset', - unique_together=set([('ip', 'port')]), - ), - - migrations.RunPython(add_default_group), ] diff --git a/apps/assets/migrations/0002_auto_20180105_1807.py b/apps/assets/migrations/0002_auto_20180105_1807.py index bf1f022ac..22c114cf8 100644 --- a/apps/assets/migrations/0002_auto_20180105_1807.py +++ b/apps/assets/migrations/0002_auto_20180105_1807.py @@ -1,35 +1,115 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-05 10:07 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -from django.db import migrations +import json +import assets.models.asset.common +from django.db.models import F, Q +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True dependencies = [ ('assets', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AlterModelOptions( - name='adminuser', - options={'ordering': ['name'], 'verbose_name': 'Admin user'}, + migrations.AddField( + model_name='favoriteasset', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), ), - migrations.AlterModelOptions( + migrations.AlterUniqueTogether( + name='domain', + unique_together={('org_id', 'name')}, + ), + migrations.AddField( + model_name='baseautomation', + name='assets', + field=models.ManyToManyField(blank=True, to='assets.asset', verbose_name='Assets'), + ), + migrations.AddField( + model_name='baseautomation', + name='nodes', + field=models.ManyToManyField(blank=True, to='assets.node', verbose_name='Node'), + ), + migrations.AddField( + model_name='automationexecution', + name='automation', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'), + ), + migrations.AddField( + model_name='asset', + name='domain', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.domain', verbose_name='Zone'), + ), + migrations.AddField( + model_name='asset', + name='nodes', + field=models.ManyToManyField(default=assets.models.asset.common.default_node, related_name='assets', to='assets.node', verbose_name='Nodes'), + ), + migrations.AddField( + model_name='asset', + name='platform', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assets', to='assets.platform', verbose_name='Platform'), + ), + migrations.CreateModel( + name='AssetBaseAutomation', + fields=[ + ], + options={ + 'verbose_name': 'Asset automation task', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.baseautomation',), + ), + migrations.CreateModel( + name='GatherFactsAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Gather asset facts', + }, + bases=('assets.assetbaseautomation',), + ), + migrations.CreateModel( + name='PingAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Ping asset', + }, + bases=('assets.assetbaseautomation',), + ), + migrations.AlterUniqueTogether( + name='favoriteasset', + unique_together={('user', 'asset')}, + ), + migrations.AlterUniqueTogether( + name='baseautomation', + unique_together={('org_id', 'name', 'type')}, + ), + migrations.AlterUniqueTogether( name='asset', - options={'verbose_name': 'Asset'}, + unique_together={('org_id', 'name')}, ), - migrations.AlterModelOptions( - name='assetgroup', - options={'ordering': ['name'], 'verbose_name': 'Asset group'}, - ), - migrations.AlterModelOptions( - name='cluster', - options={'ordering': ['name'], 'verbose_name': 'Cluster'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'verbose_name': 'System user'}, + migrations.CreateModel( + name='Gateway', + fields=[ + ], + options={ + 'verbose_name': 'Gateway', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.host',), ), ] diff --git a/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py b/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py deleted file mode 100644 index 6392158fd..000000000 --- a/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py +++ /dev/null @@ -1,158 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-28 10:16 - -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - replaces = [('assets', '0002_auto_20180105_1807'), ('assets', '0003_auto_20180109_2331'), ('assets', '0004_auto_20180125_1218'), ('assets', '0005_auto_20180126_1637'), ('assets', '0006_auto_20180130_1502'), ('assets', '0007_auto_20180225_1815'), ('assets', '0008_auto_20180306_1804'), ('assets', '0009_auto_20180307_1212')] - - dependencies = [ - ('assets', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='adminuser', - options={'ordering': ['name'], 'verbose_name': 'Admin user'}, - ), - migrations.AlterModelOptions( - name='asset', - options={'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='assetgroup', - options={'ordering': ['name'], 'verbose_name': 'Asset group'}, - ), - migrations.AlterModelOptions( - name='cluster', - options={'ordering': ['name'], 'verbose_name': 'Cluster'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'verbose_name': 'System user'}, - ), - migrations.RemoveField( - model_name='asset', - name='cluster', - ), - migrations.AlterField( - model_name='assetgroup', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - migrations.CreateModel( - name='Label', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('value', models.CharField(max_length=128, verbose_name='Value')), - ('category', models.CharField(choices=[('S', 'System'), ('U', 'User')], default='U', max_length=128, verbose_name='Category')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - options={ - 'db_table': 'assets_label', - }, - ), - migrations.AlterUniqueTogether( - name='label', - unique_together={('name', 'value')}, - ), - migrations.AddField( - model_name='asset', - name='labels', - field=models.ManyToManyField(blank=True, related_name='assets', to='assets.Label', verbose_name='Labels'), - ), - migrations.RemoveField( - model_name='asset', - name='cabinet_no', - ), - migrations.RemoveField( - model_name='asset', - name='cabinet_pos', - ), - migrations.RemoveField( - model_name='asset', - name='env', - ), - migrations.RemoveField( - model_name='asset', - name='remote_card_ip', - ), - migrations.RemoveField( - model_name='asset', - name='status', - ), - migrations.RemoveField( - model_name='asset', - name='type', - ), - migrations.CreateModel( - name='Node', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('key', models.CharField(max_length=64, unique=True, verbose_name='Key')), - ('value', models.CharField(max_length=128, verbose_name='Value')), - ('child_mark', models.IntegerField(default=0)), - ('date_create', models.DateTimeField(auto_now_add=True)), - ], - ), - migrations.RemoveField( - model_name='asset', - name='groups', - ), - migrations.RemoveField( - model_name='systemuser', - name='cluster', - ), - migrations.AlterField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='assets.AdminUser', verbose_name='Admin user'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='asset', - name='nodes', - field=models.ManyToManyField(default=assets.models.asset.default_node, related_name='assets', to='assets.Node', verbose_name='Node'), - ), - migrations.AddField( - model_name='systemuser', - name='nodes', - field=models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Nodes'), - ), - migrations.AlterField( - model_name='adminuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='systemuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0003_auto_20180109_2331.py b/apps/assets/migrations/0003_auto_20180109_2331.py index 097bc607a..ccec49608 100644 --- a/apps/assets/migrations/0003_auto_20180109_2331.py +++ b/apps/assets/migrations/0003_auto_20180109_2331.py @@ -1,17 +1,2223 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-09 15:31 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion +import json +from functools import reduce + +from django.db import migrations +from django.db.models import F + +from assets.const import AllTypes + +platforms_data_json = '''[ + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Linux", + "category": "host", + "type": "linux", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "ping_method": "posix_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_posix", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_posix", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_posix", + "push_account_params": { + "sudo": "/bin/whoami", + "shell": "/bin/bash", + "home": "", + "groups": "" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_posix", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_posix", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_posix", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + }, + { + "name": "sftp", + "port": 22, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "sftp_home": "/tmp" + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Unix", + "category": "host", + "type": "unix", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "ping_method": "posix_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_posix", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_posix", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_posix", + "push_account_params": { + "sudo": "/bin/whoami", + "shell": "/bin/bash", + "home": "", + "groups": "" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_posix", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_posix", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_posix", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "macOS", + "category": "host", + "type": "unix", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "ping_method": "posix_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_posix", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_posix", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_posix", + "push_account_params": { + "sudo": "/bin/whoami", + "shell": "/bin/bash", + "home": "", + "groups": "" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_posix", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_posix", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_posix", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "BSD", + "category": "host", + "type": "unix", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "ping_method": "posix_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_posix", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_posix", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_posix", + "push_account_params": { + "sudo": "/bin/whoami", + "shell": "/bin/bash", + "home": "", + "groups": "" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_posix", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_posix", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_posix", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Windows", + "category": "host", + "type": "windows", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "ping_method": "ping_by_rdp", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_windows", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_local_windows", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_local_windows", + "push_account_params": { + "groups": "Users,Remote Desktop Users" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_by_rdp", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_windows", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_windows", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + }, + { + "name": "ssh", + "port": 22, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "winrm", + "port": 5985, + "primary": false, + "required": false, + "default": false, + "public": false, + "setting": { + "use_ssl": false + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Windows2016", + "category": "host", + "type": "windows", + "meta": { + "security": "any" + }, + "internal": false, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "smart" + }, + "ping_enabled": true, + "ping_method": "ping_by_rdp", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_windows", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_local_windows", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_local_windows", + "push_account_params": { + "groups": "Users,Remote Desktop Users" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_by_rdp", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_windows", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_windows", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "primary": true, + "required": false, + "default": true, + "public": true, + "setting": { + "console": false, + "security": "any", + "ad_domain": "" + } + }, + { + "name": "ssh", + "port": 22, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "old_ssh_version": false + } + }, + { + "name": "sftp", + "port": 22, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "sftp_home": "/tmp" + } + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": {} + }, + { + "name": "winrm", + "port": 5985, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "use_ssl": false + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Other", + "category": "host", + "type": "other", + "meta": {}, + "internal": false, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": true, + "public": true, + "setting": { + "old_ssh_version": false + } + }, + { + "name": "sftp", + "port": 22, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "username_prompt": "username:|login:", + "password_prompt": "password:", + "success_prompt": "success|成功|#|>" + } + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "console": false, + "security": "any", + "ad_domain": "" + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Windows-RDP", + "category": "host", + "type": "windows", + "meta": { + "security": "rdp" + }, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "ping_method": "win_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_windows", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_local_windows", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_local_windows", + "push_account_params": { + "groups": "Users,Remote Desktop Users" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_windows", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_windows", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_windows", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "rdp" + } + }, + { + "name": "ssh", + "port": 22, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "winrm", + "port": 5985, + "primary": false, + "required": false, + "default": false, + "public": false, + "setting": { + "use_ssl": false + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Windows-TLS", + "category": "host", + "type": "windows", + "meta": { + "security": "tls" + }, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "ping_method": "win_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_windows", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_local_windows", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_local_windows", + "push_account_params": { + "groups": "Users,Remote Desktop Users" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_windows", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_windows", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_windows", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "tls" + } + }, + { + "name": "ssh", + "port": 22, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "winrm", + "port": 5985, + "primary": false, + "required": false, + "default": false, + "public": false, + "setting": { + "use_ssl": false + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "AIX", + "category": "host", + "type": "unix", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "ping_method": "posix_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_posix", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_aix", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_aix", + "push_account_params": { + "sudo": "/bin/whoami", + "shell": "/bin/bash", + "home": "", + "groups": "" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_posix", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_posix", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_posix", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Gateway", + "category": "host", + "type": "linux", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "ping_method": "posix_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_posix", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_posix", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_posix", + "push_account_params": { + "sudo": "/bin/whoami", + "shell": "/bin/bash", + "home": "", + "groups": "" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_posix", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_posix", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_posix", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + }, + { + "name": "sftp", + "port": 22, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "sftp_home": "/tmp" + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "RemoteAppHost", + "category": "host", + "type": "windows", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "ping_method": "win_ping", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_windows", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_local_windows", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_local_windows", + "push_account_params": { + "groups": "Users,Remote Desktop Users" + }, + "verify_account_enabled": true, + "verify_account_method": "verify_account_windows", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_windows", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_windows", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + }, + { + "name": "ssh", + "port": 22, + "primary": false, + "required": false, + "default": true, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "winrm", + "port": 5985, + "primary": false, + "required": false, + "default": false, + "public": false, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "General", + "category": "device", + "type": "general", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local", + "first_connect_delay": 0.5 + }, + "ping_enabled": true, + "ping_method": "ping_by_ssh", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_by_ssh", + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_by_ssh", + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Cisco", + "category": "device", + "type": "general", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": "enable", + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local", + "first_connect_delay": 0.5 + }, + "ping_enabled": true, + "ping_method": "ping_by_ssh", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_by_ssh", + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_by_ssh", + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Huawei", + "category": "device", + "type": "general", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": "super", + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "network_cli", + "first_connect_delay": 0.5, + "ansible_network_os":"ce" + }, + "ping_enabled": true, + "ping_method": "ping_by_ssh", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_by_ssh", + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_by_ssh", + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "H3C", + "category": "device", + "type": "general", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": true, + "su_method": "super_level", + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local", + "first_connect_delay": 0.5 + }, + "ping_enabled": true, + "ping_method": "ping_by_ssh", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_by_ssh", + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_by_ssh", + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "telnet", + "port": 23, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "MySQL", + "category": "database", + "type": "mysql", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "ping_method": "mysql_ping", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_mysql", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_mysql", + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_mysql", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_mysql", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_mysql", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "mysql", + "port": 3306, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "MariaDB", + "category": "database", + "type": "mariadb", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "ping_method": "mysql_ping", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_mysql", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_mysql", + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_mysql", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_mysql", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_mysql", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "mariadb", + "port": 3306, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "PostgreSQL", + "category": "database", + "type": "postgresql", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "ping_method": "ping_postgresql", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_postgresql", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_postgresql", + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_postgresql", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_postgresql", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_postgresql", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "postgresql", + "port": 5432, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Oracle", + "category": "database", + "type": "oracle", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "ping_method": "oracle_ping", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_oracle", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_oracle", + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_oracle", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_oracle", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_oracle", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "oracle", + "port": 1521, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "SQLServer", + "category": "database", + "type": "sqlserver", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "ping_method": "sqlserver_ping", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_sqlserver", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_sqlserver", + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_sqlserver", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_sqlserver", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "sqlserver", + "port": 1433, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "ClickHouse", + "category": "database", + "type": "clickhouse", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "clickhouse", + "port": 9000, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "MongoDB", + "category": "database", + "type": "mongodb", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "ping_method": "mongodb_ping", + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_mongodb", + "change_secret_params": {}, + "push_account_enabled": true, + "push_account_method": "push_account_mongodb", + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_mongodb", + "verify_account_params": {}, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_mongodb", + "gather_accounts_params": {}, + "remove_account_enabled": true, + "remove_account_method": "remove_account_mongodb", + "remove_account_params": {} + }, + "protocols": [ + { + "name": "mongodb", + "port": 27017, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Redis", + "category": "database", + "type": "redis", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "redis", + "port": 6379, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "auth_username": false + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Redis6+", + "category": "database", + "type": "redis", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "redis", + "port": 6379, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "auth_username": true + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Website", + "category": "web", + "type": "website", + "meta": {}, + "internal": true, + "domain_enabled": false, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "http", + "port": 80, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "username_selector": "name=username", + "password_selector": "name=password", + "submit_selector": "id=login_button", + "safe_mode": false + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Vmware-vSphere", + "category": "cloud", + "type": "private", + "meta": {}, + "internal": true, + "domain_enabled": false, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "http", + "port": 80, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "username_selector": "name=username", + "password_selector": "name=password", + "submit_selector": "id=login_button", + "safe_mode": false + } + } + ] + }, + { + "created_by": null, + "updated_by": null, + "comment": "", + "name": "Kubernetes", + "category": "cloud", + "type": "k8s", + "meta": {}, + "internal": true, + "domain_enabled": false, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "k8s", + "port": 443, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": "System", + "updated_by": "System", + "comment": "ChatGPT", + "name": "ChatGPT", + "category": "gpt", + "type": "chatgpt", + "meta": {}, + "internal": true, + "domain_enabled": false, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "chatgpt", + "port": 443, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "api_mode": "gpt-3.5-turbo" + } + } + ] + }, + { + "created_by": "System", + "updated_by": "System", + "comment": "DB2", + "name": "DB2", + "category": "database", + "type": "db2", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "db2", + "port": 50000, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + }, + { + "created_by": "System", + "updated_by": "System", + "comment": "Dameng", + "name": "Dameng", + "category": "database", + "type": "dameng", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "ping_enabled": false, + "ping_method": null, + "ping_params": {}, + "gather_facts_enabled": false, + "gather_facts_method": null, + "gather_facts_params": {}, + "change_secret_enabled": false, + "change_secret_method": null, + "change_secret_params": {}, + "push_account_enabled": false, + "push_account_method": null, + "push_account_params": {}, + "verify_account_enabled": false, + "verify_account_method": null, + "verify_account_params": {}, + "gather_accounts_enabled": false, + "gather_accounts_method": null, + "gather_accounts_params": {}, + "remove_account_enabled": false, + "remove_account_method": null, + "remove_account_params": {} + }, + "protocols": [ + { + "name": "dameng", + "port": 5236, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": {} + } + ] + } +]''' + + +def create_internal_platforms(apps, *args): + platform_cls = apps.get_model('assets', 'Platform') + automation_cls = apps.get_model('assets', 'PlatformAutomation') + platforms_data = json.loads(platforms_data_json) + + for platform_data in platforms_data: + protocols = platform_data.pop('protocols', []) + platform_data['protocols'] = [p for p in protocols if p.pop('primary', True) is not None] + AllTypes.create_or_update_by_platform_data(platform_data, platform_cls=platform_cls, + automation_cls=automation_cls) + + +def migrate_automation_ansible_remove_account(apps, *args): + automation_model = apps.get_model('assets', 'PlatformAutomation') + automation_map = { + ('oracle',): 'remove_account_oracle', + ('windows',): 'remove_account_windows', + ('mongodb',): 'remove_account_mongodb', + ('linux', 'unix'): 'remove_account_posix', + ('sqlserver',): 'remove_account_sqlserver', + ('mysql', 'mariadb'): 'remove_account_mysql', + ('postgresql',): 'remove_account_postgresql', + } + + update_objs = [] + types = list(reduce(lambda x, y: x + y, automation_map.keys())) + qs = automation_model.objects.filter(platform__type__in=types).annotate(tp=F('platform__type')) + for automation in qs: + for types, method in automation_map.items(): + if automation.tp in types: + automation.remove_account_enabled = True + automation.remove_account_method = method + break + update_objs.append(automation) + automation_model.objects.bulk_update(update_objs, ['remove_account_enabled', 'remove_account_method']) class Migration(migrations.Migration): - dependencies = [ ('assets', '0002_auto_20180105_1807'), ] operations = [ + migrations.RunPython(create_internal_platforms), + migrations.RunPython(migrate_automation_ansible_remove_account), ] diff --git a/apps/assets/migrations/0004_auto_20180125_1218.py b/apps/assets/migrations/0004_auto_20180125_1218.py deleted file mode 100644 index 1886fa499..000000000 --- a/apps/assets/migrations/0004_auto_20180125_1218.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-25 04:18 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0003_auto_20180109_2331'), - ] - - operations = [ - migrations.AlterField( - model_name='assetgroup', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/assets/migrations/0005_auto_20180126_1637.py b/apps/assets/migrations/0005_auto_20180126_1637.py deleted file mode 100644 index 8db19e482..000000000 --- a/apps/assets/migrations/0005_auto_20180126_1637.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-26 08:37 -from __future__ import unicode_literals - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0004_auto_20180125_1218'), - ] - - operations = [ - migrations.CreateModel( - name='Label', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('value', models.CharField(max_length=128, verbose_name='Value')), - ('category', models.CharField(choices=[('S', 'System'), ('U', 'User')], default='U', max_length=128, verbose_name='Category')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - options={ - 'db_table': 'assets_label', - }, - ), - migrations.AlterUniqueTogether( - name='label', - unique_together=set([('name', 'value')]), - ), - migrations.AddField( - model_name='asset', - name='labels', - field=models.ManyToManyField(blank=True, related_name='assets', to='assets.Label', verbose_name='Labels'), - ), - ] diff --git a/apps/assets/migrations/0006_auto_20180130_1502.py b/apps/assets/migrations/0006_auto_20180130_1502.py deleted file mode 100644 index b77470d27..000000000 --- a/apps/assets/migrations/0006_auto_20180130_1502.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-30 07:02 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0005_auto_20180126_1637'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='cabinet_no', - ), - migrations.RemoveField( - model_name='asset', - name='cabinet_pos', - ), - migrations.RemoveField( - model_name='asset', - name='env', - ), - migrations.RemoveField( - model_name='asset', - name='remote_card_ip', - ), - migrations.RemoveField( - model_name='asset', - name='status', - ), - migrations.RemoveField( - model_name='asset', - name='type', - ), - ] diff --git a/apps/assets/migrations/0007_auto_20180225_1815.py b/apps/assets/migrations/0007_auto_20180225_1815.py deleted file mode 100644 index 1097dd182..000000000 --- a/apps/assets/migrations/0007_auto_20180225_1815.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-02-25 10:15 -from __future__ import unicode_literals - -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0006_auto_20180130_1502'), - ] - - operations = [ - migrations.CreateModel( - name='Node', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('key', models.CharField(max_length=64, unique=True, verbose_name='Key')), - ('value', models.CharField(max_length=128, unique=True, verbose_name='Value')), - ('child_mark', models.IntegerField(default=0)), - ('date_create', models.DateTimeField(auto_now_add=True)), - ], - ), - migrations.RemoveField( - model_name='asset', - name='cluster', - ), - migrations.RemoveField( - model_name='asset', - name='groups', - ), - migrations.RemoveField( - model_name='systemuser', - name='cluster', - ), - migrations.AlterField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='assets.AdminUser', verbose_name='Admin user'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='asset', - name='nodes', - field=models.ManyToManyField(default=assets.models.default_node, related_name='assets', to='assets.Node', verbose_name='Node'), - ), - migrations.AddField( - model_name='systemuser', - name='nodes', - field=models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Nodes'), - ), - ] diff --git a/apps/assets/migrations/0008_auto_20180306_1804.py b/apps/assets/migrations/0008_auto_20180306_1804.py deleted file mode 100644 index 48d352619..000000000 --- a/apps/assets/migrations/0008_auto_20180306_1804.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-06 10:04 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0007_auto_20180225_1815'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='systemuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0009_auto_20180307_1212.py b/apps/assets/migrations/0009_auto_20180307_1212.py deleted file mode 100644 index 08d770642..000000000 --- a/apps/assets/migrations/0009_auto_20180307_1212.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-07 04:12 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0008_auto_20180306_1804'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, verbose_name='Value'), - ), - ] diff --git a/apps/assets/migrations/0010_auto_20180307_1749.py b/apps/assets/migrations/0010_auto_20180307_1749.py deleted file mode 100644 index 5e6be0943..000000000 --- a/apps/assets/migrations/0010_auto_20180307_1749.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-07 09:49 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0009_auto_20180307_1212'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, unique=True, verbose_name='Value'), - ), - ] diff --git a/apps/assets/migrations/0010_auto_20180307_1749_squashed_0019_auto_20180816_1320.py b/apps/assets/migrations/0010_auto_20180307_1749_squashed_0019_auto_20180816_1320.py deleted file mode 100644 index 364e36d1f..000000000 --- a/apps/assets/migrations/0010_auto_20180307_1749_squashed_0019_auto_20180816_1320.py +++ /dev/null @@ -1,220 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-28 10:16 - -import assets.models.utils -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -# Functions from the following migrations need manual copying. -# Move them and any dependencies into this file, then update the -# RunPython operations to refer to the local versions: -# assets.migrations.0017_auto_20180702_1415 - -def migrate_win_to_ssh_protocol(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - asset_model.objects.using(db_alias).filter(platform__startswith='Win').update(protocol='rdp') - - -class Migration(migrations.Migration): - - replaces = [('assets', '0010_auto_20180307_1749'), ('assets', '0011_auto_20180326_0957'), ('assets', '0012_auto_20180404_1302'), ('assets', '0013_auto_20180411_1135'), ('assets', '0014_auto_20180427_1245'), ('assets', '0015_auto_20180510_1235'), ('assets', '0016_auto_20180511_1203'), ('assets', '0017_auto_20180702_1415'), ('assets', '0018_auto_20180807_1116'), ('assets', '0019_auto_20180816_1320')] - - dependencies = [ - ('assets', '0009_auto_20180307_1212'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, unique=True, verbose_name='Value'), - ), - migrations.CreateModel( - name='Domain', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - ), - migrations.CreateModel( - name='Gateway', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('ip', models.GenericIPAddressField(db_index=True, verbose_name='IP')), - ('port', models.IntegerField(default=22, verbose_name='Port')), - ('protocol', models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol')), - ('comment', models.CharField(blank=True, max_length=128, null=True, verbose_name='Comment')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Domain', verbose_name='Domain')), - ], - options={ - 'abstract': False, - }, - ), - migrations.AddField( - model_name='asset', - name='domain', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.Domain', verbose_name='Domain'), - ), - migrations.AddField( - model_name='systemuser', - name='assets', - field=models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AlterField( - model_name='systemuser', - name='sudo', - field=models.TextField(default='/bin/whoami', verbose_name='Sudo'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, verbose_name='Value'), - ), - migrations.AddField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='systemuser', - name='login_mode', - field=models.CharField(choices=[('auto', 'Automatic login'), ('manual', 'Manually login')], default='auto', max_length=10, verbose_name='Login mode'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Windows2016', 'Windows(2016)'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.RunPython( - code=migrate_win_to_ssh_protocol, - ), - migrations.AddField( - model_name='adminuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='asset', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='domain', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='gateway', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='label', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='node', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='systemuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AlterField( - model_name='adminuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='asset', - name='hostname', - field=models.CharField(max_length=128, verbose_name='Hostname'), - ), - migrations.AlterField( - model_name='gateway', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='systemuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='adminuser', - unique_together={('name', 'org_id')}, - ), - migrations.AddField( - model_name='asset', - name='cpu_vcpus', - field=models.IntegerField(null=True, verbose_name='CPU vcpus'), - ), - migrations.AlterUniqueTogether( - name='asset', - unique_together={('org_id', 'hostname')}, - ), - migrations.AlterUniqueTogether( - name='gateway', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='systemuser', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='label', - unique_together={('name', 'value', 'org_id')}, - ), - ] diff --git a/apps/assets/migrations/0011_auto_20180326_0957.py b/apps/assets/migrations/0011_auto_20180326_0957.py deleted file mode 100644 index 07b9055dc..000000000 --- a/apps/assets/migrations/0011_auto_20180326_0957.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-26 01:57 -from __future__ import unicode_literals - -import assets.models.utils -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0010_auto_20180307_1749'), - ] - - operations = [ - migrations.CreateModel( - name='Domain', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - ), - migrations.CreateModel( - name='Gateway', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(max_length=128, verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('ip', models.GenericIPAddressField(db_index=True, verbose_name='IP')), - ('port', models.IntegerField(default=22, verbose_name='Port')), - ('protocol', models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol')), - ('comment', models.CharField(blank=True, max_length=128, null=True, verbose_name='Comment')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Domain', verbose_name='Domain')), - ], - options={ - 'abstract': False, - }, - ), - migrations.AddField( - model_name='asset', - name='domain', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='assets', to='assets.Domain', verbose_name='Domain'), - ), - ] diff --git a/apps/assets/migrations/0012_auto_20180404_1302.py b/apps/assets/migrations/0012_auto_20180404_1302.py deleted file mode 100644 index 0ccb63e27..000000000 --- a/apps/assets/migrations/0012_auto_20180404_1302.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-04 05:02 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0011_auto_20180326_0957'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='domain', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.Domain', verbose_name='Domain'), - ), - ] diff --git a/apps/assets/migrations/0013_auto_20180411_1135.py b/apps/assets/migrations/0013_auto_20180411_1135.py deleted file mode 100644 index baaf789bd..000000000 --- a/apps/assets/migrations/0013_auto_20180411_1135.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-11 03:35 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0012_auto_20180404_1302'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='assets', - field=models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AlterField( - model_name='systemuser', - name='sudo', - field=models.TextField(default='/bin/whoami', verbose_name='Sudo'), - ), - ] diff --git a/apps/assets/migrations/0014_auto_20180427_1245.py b/apps/assets/migrations/0014_auto_20180427_1245.py deleted file mode 100644 index 735a50879..000000000 --- a/apps/assets/migrations/0014_auto_20180427_1245.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-27 04:45 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0013_auto_20180411_1135'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0015_auto_20180510_1235.py b/apps/assets/migrations/0015_auto_20180510_1235.py deleted file mode 100644 index 81d12d2e4..000000000 --- a/apps/assets/migrations/0015_auto_20180510_1235.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-05-10 04:35 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0014_auto_20180427_1245'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0016_auto_20180511_1203.py b/apps/assets/migrations/0016_auto_20180511_1203.py deleted file mode 100644 index 32f79a3c6..000000000 --- a/apps/assets/migrations/0016_auto_20180511_1203.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-05-11 04:03 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0015_auto_20180510_1235'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, verbose_name='Value'), - ), - ] diff --git a/apps/assets/migrations/0017_auto_20180702_1415.py b/apps/assets/migrations/0017_auto_20180702_1415.py deleted file mode 100644 index 9950424a6..000000000 --- a/apps/assets/migrations/0017_auto_20180702_1415.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-07-02 06:15 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -def migrate_win_to_ssh_protocol(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - asset_model.objects.using(db_alias).filter(platform__startswith='Win').update(protocol='rdp') - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0016_auto_20180511_1203'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='systemuser', - name='login_mode', - field=models.CharField(choices=[('auto', 'Automatic login'), ('manual', 'Manually login')], default='auto', max_length=10, verbose_name='Login mode'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Windows2016', 'Windows(2016)'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.RunPython(migrate_win_to_ssh_protocol), - ] diff --git a/apps/assets/migrations/0018_auto_20180807_1116.py b/apps/assets/migrations/0018_auto_20180807_1116.py deleted file mode 100644 index c4e848b43..000000000 --- a/apps/assets/migrations/0018_auto_20180807_1116.py +++ /dev/null @@ -1,84 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-07 03:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0017_auto_20180702_1415'), - ] - - operations = [ - migrations.AddField( - model_name='adminuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='asset', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='domain', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='gateway', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='label', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='node', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='systemuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AlterField( - model_name='adminuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='asset', - name='hostname', - field=models.CharField(max_length=128, verbose_name='Hostname'), - ), - migrations.AlterField( - model_name='gateway', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='systemuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='adminuser', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='asset', - unique_together={('org_id', 'hostname')}, - ), - migrations.AlterUniqueTogether( - name='gateway', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='systemuser', - unique_together={('name', 'org_id')}, - ), - ] diff --git a/apps/assets/migrations/0019_auto_20180816_1320.py b/apps/assets/migrations/0019_auto_20180816_1320.py deleted file mode 100644 index 0d468e511..000000000 --- a/apps/assets/migrations/0019_auto_20180816_1320.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-16 05:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0018_auto_20180807_1116'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='cpu_vcpus', - field=models.IntegerField(null=True, verbose_name='CPU vcpus'), - ), - migrations.AlterUniqueTogether( - name='label', - unique_together={('name', 'value', 'org_id')}, - ), - ] diff --git a/apps/assets/migrations/0020_auto_20180816_1652.py b/apps/assets/migrations/0020_auto_20180816_1652.py deleted file mode 100644 index 8639c4022..000000000 --- a/apps/assets/migrations/0020_auto_20180816_1652.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-16 08:52 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0019_auto_20180816_1320'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='asset', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='domain', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='gateway', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='label', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='node', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='systemuser', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - ] diff --git a/apps/assets/migrations/0021_auto_20180903_1132.py b/apps/assets/migrations/0021_auto_20180903_1132.py deleted file mode 100644 index 2475bb4de..000000000 --- a/apps/assets/migrations/0021_auto_20180903_1132.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.1 on 2018-09-03 03:32 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0020_auto_20180816_1652'), - ] - - operations = [ - migrations.AlterModelOptions( - name='domain', - options={'verbose_name': 'Domain'}, - ), - migrations.AlterModelOptions( - name='gateway', - options={'verbose_name': 'Gateway'}, - ), - migrations.AlterModelOptions( - name='node', - options={'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0022_auto_20181012_1717.py b/apps/assets/migrations/0022_auto_20181012_1717.py deleted file mode 100644 index 8849249ea..000000000 --- a/apps/assets/migrations/0022_auto_20181012_1717.py +++ /dev/null @@ -1,56 +0,0 @@ -# Generated by Django 2.1.1 on 2018-10-12 09:17 - -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0021_auto_20180903_1132'), - ] - - operations = [ - migrations.CreateModel( - name='CommandFilter', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=64, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('created_by', models.CharField(blank=True, default='', max_length=128, verbose_name='Created by')), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='CommandFilterRule', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('type', models.CharField(choices=[('regex', 'Regex'), ('command', 'Command')], default='command', max_length=16, verbose_name='Type')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), - ('content', models.TextField(help_text='One line one command', max_length=1024, verbose_name='Content')), - ('action', models.IntegerField(choices=[(0, 'Deny'), (1, 'Allow')], default=0, verbose_name='Action')), - ('comment', models.CharField(blank=True, default='', max_length=64, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(blank=True, default='', max_length=128, verbose_name='Created by')), - ('filter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rules', to='assets.CommandFilter', verbose_name='Filter')), - ], - options={ - 'ordering': ('priority', 'action'), - }, - ), - migrations.AddField( - model_name='systemuser', - name='cmd_filters', - field=models.ManyToManyField(blank=True, related_name='system_users', to='assets.CommandFilter', verbose_name='Command filter'), - ), - ] diff --git a/apps/assets/migrations/0023_auto_20181016_1650.py b/apps/assets/migrations/0023_auto_20181016_1650.py deleted file mode 100644 index f7ecd1b4f..000000000 --- a/apps/assets/migrations/0023_auto_20181016_1650.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.1 on 2018-10-16 08:50 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0022_auto_20181012_1717'), - ] - - operations = [ - migrations.AlterModelOptions( - name='commandfilterrule', - options={'ordering': ('-priority', 'action')}, - ), - migrations.AlterField( - model_name='commandfilterrule', - name='priority', - field=models.IntegerField(default=50, help_text='1-100, the higher will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - migrations.AlterField( - model_name='systemuser', - name='priority', - field=models.IntegerField(default=20, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - ] diff --git a/apps/assets/migrations/0024_auto_20181219_1614.py b/apps/assets/migrations/0024_auto_20181219_1614.py deleted file mode 100644 index 5e6a6c4e3..000000000 --- a/apps/assets/migrations/0024_auto_20181219_1614.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.4 on 2018-12-19 08:14 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0023_auto_20181016_1650'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)'), ('vnc', 'vnc')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)'), ('vnc', 'vnc')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0025_auto_20190221_1902.py b/apps/assets/migrations/0025_auto_20190221_1902.py deleted file mode 100644 index 7124bb509..000000000 --- a/apps/assets/migrations/0025_auto_20190221_1902.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-21 11:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0024_auto_20181219_1614'), - ] - - operations = [ - migrations.AlterModelOptions( - name='commandfilter', - options={'verbose_name': 'Command filter'}, - ), - migrations.AlterModelOptions( - name='commandfilterrule', - options={'ordering': ('-priority', 'action'), 'verbose_name': 'Command filter rule'}, - ), - ] diff --git a/apps/assets/migrations/0026_auto_20190325_2035.py b/apps/assets/migrations/0026_auto_20190325_2035.py deleted file mode 100644 index c329658e0..000000000 --- a/apps/assets/migrations/0026_auto_20190325_2035.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-25 12:35 - -import assets.models.utils -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0025_auto_20190221_1902'), - ] - - operations = [ - migrations.CreateModel( - name='AuthBook', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('is_latest', models.BooleanField(default=False, verbose_name='Latest version')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')), - ], - options={ - 'verbose_name': 'AuthBook', - }, - ), - migrations.AlterModelOptions( - name='node', - options={'ordering': ['key'], 'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0027_auto_20190521_1703.py b/apps/assets/migrations/0027_auto_20190521_1703.py deleted file mode 100644 index 91446019f..000000000 --- a/apps/assets/migrations/0027_auto_20190521_1703.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-21 09:03 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0026_auto_20190325_2035'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='ip', - field=models.CharField(db_index=True, max_length=128, verbose_name='IP'), - ), - migrations.AlterField( - model_name='asset', - name='public_ip', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Public IP'), - ), - ] diff --git a/apps/assets/migrations/0028_protocol.py b/apps/assets/migrations/0028_protocol.py deleted file mode 100644 index 82b311c11..000000000 --- a/apps/assets/migrations/0028_protocol.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-22 02:58 - -import uuid - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0027_auto_20190521_1703'), - ] - - operations = [ - migrations.CreateModel( - name='Protocol', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', - models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)'), ('vnc', 'vnc')], - default='ssh', max_length=16, verbose_name='Name')), - ('port', models.IntegerField(default=22, validators=[django.core.validators.MaxValueValidator(65535), - django.core.validators.MinValueValidator(0)], - verbose_name='Port')), - ], - ), - migrations.AddField( - model_name='asset', - name='protocols', - field=models.ManyToManyField(to='assets.Protocol', - verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0029_auto_20190522_1114.py b/apps/assets/migrations/0029_auto_20190522_1114.py deleted file mode 100644 index 46836c846..000000000 --- a/apps/assets/migrations/0029_auto_20190522_1114.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-22 03:14 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0028_protocol'), - ] - - operations = [ - ] diff --git a/apps/assets/migrations/0030_auto_20190619_1135.py b/apps/assets/migrations/0030_auto_20190619_1135.py deleted file mode 100644 index a4b6969aa..000000000 --- a/apps/assets/migrations/0030_auto_20190619_1135.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-19 03:35 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0029_auto_20190522_1114'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='assets', to='assets.AdminUser', verbose_name='Admin user'), - ), - ] diff --git a/apps/assets/migrations/0031_auto_20190621_1332.py b/apps/assets/migrations/0031_auto_20190621_1332.py deleted file mode 100644 index c2e614cbc..000000000 --- a/apps/assets/migrations/0031_auto_20190621_1332.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-21 05:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0030_auto_20190619_1135'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='adminuser', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AlterField( - model_name='authbook', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='authbook', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AlterField( - model_name='gateway', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='gateway', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AlterField( - model_name='systemuser', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='systemuser', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - ] diff --git a/apps/assets/migrations/0032_auto_20190624_2108.py b/apps/assets/migrations/0032_auto_20190624_2108.py deleted file mode 100644 index 275308e99..000000000 --- a/apps/assets/migrations/0032_auto_20190624_2108.py +++ /dev/null @@ -1,75 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-24 13:08 - -import assets.models.utils -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0031_auto_20190621_1332'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='adminuser', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='adminuser', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - migrations.AlterField( - model_name='authbook', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='authbook', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='authbook', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - migrations.AlterField( - model_name='gateway', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='gateway', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='gateway', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - migrations.AlterField( - model_name='systemuser', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='systemuser', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='systemuser', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - ] diff --git a/apps/assets/migrations/0033_auto_20190624_2108.py b/apps/assets/migrations/0033_auto_20190624_2108.py deleted file mode 100644 index dc89bc125..000000000 --- a/apps/assets/migrations/0033_auto_20190624_2108.py +++ /dev/null @@ -1,73 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-24 13:08 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0032_auto_20190624_2108'), - ] - - operations = [ - migrations.RenameField( - model_name='adminuser', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='adminuser', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='authbook', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='authbook', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='gateway', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='gateway', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='systemuser', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='systemuser', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='adminuser', - old_name='_password', - new_name='password', - ), - migrations.RenameField( - model_name='authbook', - old_name='_password', - new_name='password', - ), - migrations.RenameField( - model_name='gateway', - old_name='_password', - new_name='password', - ), - migrations.RenameField( - model_name='systemuser', - old_name='_password', - new_name='password', - ), - ] diff --git a/apps/assets/migrations/0034_auto_20190705_1348.py b/apps/assets/migrations/0034_auto_20190705_1348.py deleted file mode 100644 index 161ce2b30..000000000 --- a/apps/assets/migrations/0034_auto_20190705_1348.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-05 05:48 - -from django.db import migrations -from django.db.models import F -from django.db.models import CharField, Value as V -from django.db.models.functions import Concat - - -def migrate_assets_protocol(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - assets = asset_model.objects.using(db_alias).all().annotate( - protocols_new=Concat( - 'protocol', V('/'), 'port', - output_field=CharField(), - ), - ) - assets.update(protocols=F('protocols_new')) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0033_auto_20190624_2108'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='protocols', - ), - migrations.AddField( - model_name='asset', - name='protocols', - field=CharField(blank=True, default='ssh/22', max_length=128, verbose_name='Protocols'), - ), - migrations.RunPython(migrate_assets_protocol), - migrations.DeleteModel(name='Protocol'), - ] diff --git a/apps/assets/migrations/0035_auto_20190711_2018.py b/apps/assets/migrations/0035_auto_20190711_2018.py deleted file mode 100644 index 00eb41fe5..000000000 --- a/apps/assets/migrations/0035_auto_20190711_2018.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-11 12:18 - -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0034_auto_20190705_1348'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='authbook', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='gateway', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='systemuser', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - ] diff --git a/apps/assets/migrations/0036_auto_20190716_1535.py b/apps/assets/migrations/0036_auto_20190716_1535.py deleted file mode 100644 index 317d427f0..000000000 --- a/apps/assets/migrations/0036_auto_20190716_1535.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-16 07:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0035_auto_20190711_2018'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilter', - name='name', - field=models.CharField(max_length=64, unique=True, verbose_name='Name'), - ), - ] diff --git a/apps/assets/migrations/0037_auto_20190724_2002.py b/apps/assets/migrations/0037_auto_20190724_2002.py deleted file mode 100644 index 49c5490c5..000000000 --- a/apps/assets/migrations/0037_auto_20190724_2002.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-24 12:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0036_auto_20190716_1535'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='_become_pass', - field=models.CharField(blank=True, default='', max_length=128), - ), - ] diff --git a/apps/assets/migrations/0038_auto_20190911_1634.py b/apps/assets/migrations/0038_auto_20190911_1634.py deleted file mode 100644 index 0533f5baf..000000000 --- a/apps/assets/migrations/0038_auto_20190911_1634.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-11 08:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0037_auto_20190724_2002'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0039_authbook_is_active.py b/apps/assets/migrations/0039_authbook_is_active.py deleted file mode 100644 index 3f600cfac..000000000 --- a/apps/assets/migrations/0039_authbook_is_active.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-17 12:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0038_auto_20190911_1634'), - ] - - operations = [ - migrations.AddField( - model_name='authbook', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Is active'), - ), - ] diff --git a/apps/assets/migrations/0040_auto_20190917_2056.py b/apps/assets/migrations/0040_auto_20190917_2056.py deleted file mode 100644 index 2957a1f31..000000000 --- a/apps/assets/migrations/0040_auto_20190917_2056.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-17 12:56 - -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0039_authbook_is_active'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='authbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0041_gathereduser.py b/apps/assets/migrations/0041_gathereduser.py deleted file mode 100644 index f1b464e74..000000000 --- a/apps/assets/migrations/0041_gathereduser.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-18 04:10 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0040_auto_20190917_2056'), - ] - - operations = [ - migrations.CreateModel( - name='GatheredUser', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')), - ('present', models.BooleanField(default=True, verbose_name='Present')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')), - ], - options={'ordering': ['asset'], 'verbose_name': 'GatherUser'}, - ), - ] diff --git a/apps/assets/migrations/0042_favoriteasset.py b/apps/assets/migrations/0042_favoriteasset.py deleted file mode 100644 index a09759e26..000000000 --- a/apps/assets/migrations/0042_favoriteasset.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2.5 on 2019-10-16 08:38 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0041_gathereduser'), - ] - - operations = [ - migrations.CreateModel( - name='FavoriteAsset', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'unique_together': {('user', 'asset')}, - 'verbose_name': 'Favorite asset', - }, - ), - ] diff --git a/apps/assets/migrations/0043_auto_20191114_1111.py b/apps/assets/migrations/0043_auto_20191114_1111.py deleted file mode 100644 index a07dee6bb..000000000 --- a/apps/assets/migrations/0043_auto_20191114_1111.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.5 on 2019-11-14 03:11 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0042_favoriteasset'), - ] - - operations = [ - migrations.AddField( - model_name='gathereduser', - name='date_last_login', - field=models.DateTimeField(null=True, verbose_name='Date last login'), - ), - migrations.AddField( - model_name='gathereduser', - name='ip_last_login', - field=models.CharField(default='', max_length=39, verbose_name='IP last login'), - ), - ] diff --git a/apps/assets/migrations/0044_platform.py b/apps/assets/migrations/0044_platform.py deleted file mode 100644 index 2e1ab723e..000000000 --- a/apps/assets/migrations/0044_platform.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-06 07:26 - -import common.db.fields -from django.db import migrations, models - - -def create_internal_platform(apps, schema_editor): - model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - type_platforms = ( - ('Linux', 'Linux', None), - ('Unix', 'Unix', None), - ('MacOS', 'MacOS', None), - ('BSD', 'BSD', None), - ('Windows', 'Windows', None), - ('Windows2016', 'Windows', {'security': 'tls'}), - ('Other', 'Other', None), - ) - for name, base, meta in type_platforms: - model.objects.using(db_alias).create( - name=name, base=base, internal=True, meta=meta - ) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0043_auto_20191114_1111'), - ] - - operations = [ - migrations.CreateModel( - name='Platform', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.SlugField(allow_unicode=True, unique=True, verbose_name='Name')), - ('base', models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Other', 'Other')], default='Linux', max_length=16, verbose_name='Base')), - ('charset', models.CharField(choices=[('utf8', 'UTF-8'), ('gbk', 'GBK')], default='utf8', max_length=8, verbose_name='Charset')), - ('meta', common.db.fields.JsonDictTextField(blank=True, null=True, verbose_name='Meta')), - ('internal', models.BooleanField(default=False, verbose_name='Internal')), - ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), - ], - options={ - 'verbose_name': 'Platform' - } - ), - migrations.RunPython(create_internal_platform) - ] diff --git a/apps/assets/migrations/0045_auto_20191206_1607.py b/apps/assets/migrations/0045_auto_20191206_1607.py deleted file mode 100644 index a2a136c3b..000000000 --- a/apps/assets/migrations/0045_auto_20191206_1607.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-06 08:07 - -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion - - -def migrate_platform_to_asset_type(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - platform_model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - - platforms = platform_model.objects.using(db_alias).all() - platforms_map = {p.name: p for p in platforms} - for name, p in platforms_map.items(): - asset_model.objects.using(db_alias)\ - .filter(_platform=name)\ - .update(platform=p) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0044_platform'), - ] - - operations = [ - migrations.RenameField( - model_name='asset', - old_name='platform', - new_name='_platform', - ), - migrations.AddField( - model_name='asset', - name='platform', - field=models.ForeignKey( - default='', - on_delete=django.db.models.deletion.PROTECT, - related_name='assets', to='assets.Platform', - verbose_name='Platform'), - ), - migrations.RunPython(migrate_platform_to_asset_type), - migrations.RemoveField( - model_name='asset', - name='_platform', - ), - ] diff --git a/apps/assets/migrations/0046_auto_20191218_1705.py b/apps/assets/migrations/0046_auto_20191218_1705.py deleted file mode 100644 index af776eee2..000000000 --- a/apps/assets/migrations/0046_auto_20191218_1705.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-18 09:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0045_auto_20191206_1607'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc'), ('mysql', 'mysql')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0047_assetuser.py b/apps/assets/migrations/0047_assetuser.py deleted file mode 100644 index 6c309a0f7..000000000 --- a/apps/assets/migrations/0047_assetuser.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-06 07:34 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0046_auto_20191218_1705'), - ] - - operations = [ - migrations.CreateModel( - name='AssetUser', - fields=[ - ], - options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.authbook',), - ), - ] diff --git a/apps/assets/migrations/0048_auto_20191230_1512.py b/apps/assets/migrations/0048_auto_20191230_1512.py deleted file mode 100644 index b4bf9f9bc..000000000 --- a/apps/assets/migrations/0048_auto_20191230_1512.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-30 07:12 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0047_assetuser'), - ] - - operations = [ - migrations.RemoveField( - model_name='authbook', - name='is_active', - ), - migrations.AddField( - model_name='systemuser', - name='username_same_with_user', - field=models.BooleanField(default=False, verbose_name='Username same with user'), - ), - migrations.AddField( - model_name='systemuser', - name='users', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Users'), - ), - migrations.AddField( - model_name='systemuser', - name='groups', - field=models.ManyToManyField(blank=True, to='users.UserGroup', - verbose_name='User groups'), - ), - ] diff --git a/apps/assets/migrations/0049_systemuser_sftp_root.py b/apps/assets/migrations/0049_systemuser_sftp_root.py deleted file mode 100644 index d8e992e25..000000000 --- a/apps/assets/migrations/0049_systemuser_sftp_root.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-19 07:29 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0048_auto_20191230_1512'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='sftp_root', - field=models.CharField(default='tmp', max_length=128, verbose_name='SFTP Root'), - ), - ] diff --git a/apps/assets/migrations/0050_auto_20200711_1740.py b/apps/assets/migrations/0050_auto_20200711_1740.py deleted file mode 100644 index 231fcfbe4..000000000 --- a/apps/assets/migrations/0050_auto_20200711_1740.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-11 09:40 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0049_systemuser_sftp_root'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/assets/migrations/0051_auto_20200713_1143.py b/apps/assets/migrations/0051_auto_20200713_1143.py deleted file mode 100644 index 95ec1ca06..000000000 --- a/apps/assets/migrations/0051_auto_20200713_1143.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-13 03:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0050_auto_20200711_1740'), - ] - - operations = [ - migrations.AlterField( - model_name='domain', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='domain', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/assets/migrations/0052_auto_20200715_1535.py b/apps/assets/migrations/0052_auto_20200715_1535.py deleted file mode 100644 index 5903d635e..000000000 --- a/apps/assets/migrations/0052_auto_20200715_1535.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-15 07:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0051_auto_20200713_1143'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilter', - name='name', - field=models.CharField(max_length=64, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='commandfilter', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/assets/migrations/0053_auto_20200723_1232.py b/apps/assets/migrations/0053_auto_20200723_1232.py deleted file mode 100644 index 7d1ba220d..000000000 --- a/apps/assets/migrations/0053_auto_20200723_1232.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-23 04:32 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0052_auto_20200715_1535'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='authbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0054_auto_20200807_1032.py b/apps/assets/migrations/0054_auto_20200807_1032.py deleted file mode 100644 index 288b78e25..000000000 --- a/apps/assets/migrations/0054_auto_20200807_1032.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-07 02:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0053_auto_20200723_1232'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='token', - field=models.TextField(default='', verbose_name='Token'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc'), ('mysql', 'mysql'), ('k8s', 'k8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0055_auto_20200811_1845.py b/apps/assets/migrations/0055_auto_20200811_1845.py deleted file mode 100644 index 739378c78..000000000 --- a/apps/assets/migrations/0055_auto_20200811_1845.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-11 10:45 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0054_auto_20200807_1032'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='home', - field=models.CharField(blank=True, default='', max_length=4096, verbose_name='Home'), - ), - migrations.AddField( - model_name='systemuser', - name='system_groups', - field=models.CharField(blank=True, default='', max_length=4096, verbose_name='System groups'), - ), - ] diff --git a/apps/assets/migrations/0056_auto_20200904_1751.py b/apps/assets/migrations/0056_auto_20200904_1751.py deleted file mode 100644 index 1a7a34af1..000000000 --- a/apps/assets/migrations/0056_auto_20200904_1751.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.13 on 2020-09-04 09:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0055_auto_20200811_1845'), - ] - - operations = [ - migrations.AddField( - model_name='node', - name='assets_amount', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='node', - name='parent_key', - field=models.CharField(db_index=True, default='', max_length=64, verbose_name='Parent key'), - ), - ] diff --git a/apps/assets/migrations/0057_fill_node_value_assets_amount_and_parent_key.py b/apps/assets/migrations/0057_fill_node_value_assets_amount_and_parent_key.py deleted file mode 100644 index 458975692..000000000 --- a/apps/assets/migrations/0057_fill_node_value_assets_amount_and_parent_key.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-21 08:20 - -from django.db import migrations -from django.db.models import Q - - -def fill_node_value(apps, schema_editor): - Node = apps.get_model('assets', 'Node') - Asset = apps.get_model('assets', 'Asset') - node_queryset = Node.objects.all() - node_amount = node_queryset.count() - width = len(str(node_amount)) - print('\n') - for i, node in enumerate(node_queryset): - print(f'\t{i+1:0>{width}}/{node_amount} compute node[{node.key}]`s assets_amount ...') - assets_amount = Asset.objects.filter( - Q(nodes__key__istartswith=f'{node.key}:') | Q(nodes=node) - ).distinct().count() - key = node.key - try: - parent_key = key[:key.rindex(':')] - except ValueError: - parent_key = '' - node.assets_amount = assets_amount - node.parent_key = parent_key - node.save() - print(' ' + '.'*65, end='') - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0056_auto_20200904_1751'), - ] - - operations = [ - migrations.RunPython(fill_node_value) - ] diff --git a/apps/assets/migrations/0058_auto_20201023_1115.py b/apps/assets/migrations/0058_auto_20201023_1115.py deleted file mode 100644 index 57636611a..000000000 --- a/apps/assets/migrations/0058_auto_20201023_1115.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-23 03:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0057_fill_node_value_assets_amount_and_parent_key'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['-date_created'], 'verbose_name': 'Asset'}, - ), - migrations.AlterField( - model_name='asset', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='commandfilterrule', - name='content', - field=models.TextField(help_text='One line one command', verbose_name='Content'), - ), - ] diff --git a/apps/assets/migrations/0059_auto_20201027_1905.py b/apps/assets/migrations/0059_auto_20201027_1905.py deleted file mode 100644 index a01120fd7..000000000 --- a/apps/assets/migrations/0059_auto_20201027_1905.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-27 11:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0058_auto_20201023_1115'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc'), ('mysql', 'mysql'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('postgresql', 'postgresql'), ('k8s', 'k8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='systemuser', - name='ad_domain', - field=models.CharField(default='', max_length=256), - ), - migrations.AlterField( - model_name='gateway', - name='ip', - field=models.CharField(db_index=True, max_length=128, verbose_name='IP'), - ), - ] diff --git a/apps/assets/migrations/0060_node_full_value.py b/apps/assets/migrations/0060_node_full_value.py deleted file mode 100644 index 0f633deac..000000000 --- a/apps/assets/migrations/0060_node_full_value.py +++ /dev/null @@ -1,58 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-26 11:31 - -from django.db import migrations, models - - -def get_node_ancestor_keys(key, with_self=False): - parent_keys = [] - key_list = key.split(":") - if not with_self: - key_list.pop() - for i in range(len(key_list)): - parent_keys.append(":".join(key_list)) - key_list.pop() - return parent_keys - - -def migrate_nodes_value_with_slash(apps, schema_editor): - model = apps.get_model("assets", "Node") - db_alias = schema_editor.connection.alias - nodes = model.objects.using(db_alias).filter(value__contains='/') - print('') - print("\t- Start migrate node value if has /") - for i, node in enumerate(list(nodes)): - new_value = node.value.replace('/', '|') - print("\t - {} start migrate node value: {} => {}".format(i, node.value, new_value)) - node.value = new_value - node.save() - - -def migrate_nodes_full_value(apps, schema_editor): - model = apps.get_model("assets", "Node") - db_alias = schema_editor.connection.alias - nodes = model.objects.using(db_alias).all() - print("\n\t- Start migrate node full value") - for i, node in enumerate(list(nodes)): - print("\t - {} start migrate {} node full value".format(i, node.value)) - ancestor_keys = get_node_ancestor_keys(node.key, True) - values = model.objects.filter(key__in=ancestor_keys).values_list('key', 'value') - values = [v for k, v in sorted(values, key=lambda x: len(x[0]))] - node.full_value = '/' + '/'.join(values) - node.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0059_auto_20201027_1905'), - ] - - operations = [ - migrations.AddField( - model_name='node', - name='full_value', - field=models.CharField(default='', max_length=4096, verbose_name='Full value'), - ), - migrations.RunPython(migrate_nodes_value_with_slash), - migrations.RunPython(migrate_nodes_full_value) - ] diff --git a/apps/assets/migrations/0061_auto_20201116_1757.py b/apps/assets/migrations/0061_auto_20201116_1757.py deleted file mode 100644 index 71ddf21cf..000000000 --- a/apps/assets/migrations/0061_auto_20201116_1757.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.13 on 2020-11-16 09:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0060_node_full_value'), - ] - - operations = [ - migrations.AlterModelOptions( - name='node', - options={'ordering': ['value'], 'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0062_auto_20201117_1938.py b/apps/assets/migrations/0062_auto_20201117_1938.py deleted file mode 100644 index 9764ede39..000000000 --- a/apps/assets/migrations/0062_auto_20201117_1938.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.13 on 2020-11-17 11:38 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0061_auto_20201116_1757'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname', 'ip'], 'verbose_name': 'Asset'}, - ), - ] diff --git a/apps/assets/migrations/0063_migrate_default_node_key.py b/apps/assets/migrations/0063_migrate_default_node_key.py deleted file mode 100644 index fc294264f..000000000 --- a/apps/assets/migrations/0063_migrate_default_node_key.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by Jiangjie.Bai on 2020-12-01 10:47 - -from django.db import migrations -from django.db.models import Q - -default_node_value = 'Default' # Always -old_default_node_key = '0' # Version <= 1.4.3 -new_default_node_key = '1' # Version >= 1.4.4 - - -def compute_parent_key(key): - try: - return key[:key.rindex(':')] - except ValueError: - return '' - - -def migrate_default_node_key(apps, schema_editor): - """ 将已经存在的Default节点的key从0修改为1 """ - # 1.4.3版本中Default节点的key为0 - print('') - Node = apps.get_model('assets', 'Node') - Asset = apps.get_model('assets', 'Asset') - - # key为0的节点 - old_default_node = Node.objects.filter(key=old_default_node_key, value=default_node_value).first() - if not old_default_node: - print(f'Check old default node `key={old_default_node_key} value={default_node_value}` not exists') - return - print(f'Check old default node `key={old_default_node_key} value={default_node_value}` exists') - # key为1的节点 - new_default_node = Node.objects.filter(key=new_default_node_key, value=default_node_value).first() - if new_default_node: - print(f'Check new default node `key={new_default_node_key} value={default_node_value}` exists') - all_assets = Asset.objects.filter( - Q(nodes__key__startswith=f'{new_default_node_key}:') | Q(nodes__key=new_default_node_key) - ).distinct() - if all_assets: - print(f'Check new default node has assets (count: {len(all_assets)})') - return - all_children = Node.objects.filter(key__startswith=f'{new_default_node_key}:') - if all_children: - print(f'Check new default node has children nodes (count: {len(all_children)})') - return - print(f'Check new default node not has assets and children nodes, delete it.') - new_default_node.delete() - # 执行修改 - print(f'Modify old default node `key` from `{old_default_node_key}` to `{new_default_node_key}`') - nodes = Node.objects.filter( - Q(key__istartswith=f'{old_default_node_key}:') | Q(key=old_default_node_key) - ) - for node in nodes: - old_key = node.key - key_list = old_key.split(':', maxsplit=1) - key_list[0] = new_default_node_key - new_key = ':'.join(key_list) - node.key = new_key - node.parent_key = compute_parent_key(node.key) - # 批量更新 - print(f'Bulk update nodes `key` and `parent_key`, (count: {len(nodes)})') - Node.objects.bulk_update(nodes, ['key', 'parent_key']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0062_auto_20201117_1938'), - ] - - operations = [ - migrations.RunPython(migrate_default_node_key) - ] diff --git a/apps/assets/migrations/0064_auto_20201203_1100.py b/apps/assets/migrations/0064_auto_20201203_1100.py deleted file mode 100644 index a8119a883..000000000 --- a/apps/assets/migrations/0064_auto_20201203_1100.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1 on 2020-12-03 03:00 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0063_migrate_default_node_key'), - ] - - operations = [ - migrations.AlterModelOptions( - name='node', - options={'ordering': ['parent_key', 'value'], 'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0065_auto_20210121_1549.py b/apps/assets/migrations/0065_auto_20210121_1549.py deleted file mode 100644 index 1182de1fa..000000000 --- a/apps/assets/migrations/0065_auto_20210121_1549.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1 on 2021-01-21 07:49 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0064_auto_20201203_1100'), - ] - - operations = [ - migrations.AlterModelOptions( - name='domain', - options={'ordering': ('name',), 'verbose_name': 'Domain'}, - ), - ] diff --git a/apps/assets/migrations/0066_auto_20210208_1802.py b/apps/assets/migrations/0066_auto_20210208_1802.py deleted file mode 100644 index ffe7d8fb5..000000000 --- a/apps/assets/migrations/0066_auto_20210208_1802.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1 on 2021-02-08 10:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0065_auto_20210121_1549'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'verbose_name': 'Asset'}, - ), - ] diff --git a/apps/assets/migrations/0067_auto_20210311_1113.py b/apps/assets/migrations/0067_auto_20210311_1113.py deleted file mode 100644 index 0b087d47c..000000000 --- a/apps/assets/migrations/0067_auto_20210311_1113.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 3.1 on 2021-03-11 03:13 - -import django.core.validators -from django.db import migrations, models - - -def migrate_cmd_filter_priority(apps, schema_editor): - cmd_filter_rule_model = apps.get_model('assets', 'CommandFilterRule') - cmd_filter_rules = cmd_filter_rule_model.objects.all() - for cmd_filter_rule in cmd_filter_rules: - cmd_filter_rule.priority = 100 - cmd_filter_rule.priority + 1 - - cmd_filter_rule_model.objects.bulk_update(cmd_filter_rules, fields=['priority']) - - -def migrate_system_user_priority(apps, schema_editor): - system_user_model = apps.get_model('assets', 'SystemUser') - system_users = system_user_model.objects.all() - for system_user in system_users: - system_user.priority = 100 - system_user.priority + 1 - - system_user_model.objects.bulk_update(system_users, fields=['priority']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0066_auto_20210208_1802'), - ] - - operations = [ - migrations.RunPython(migrate_cmd_filter_priority), - migrations.RunPython(migrate_system_user_priority), - migrations.AlterModelOptions( - name='commandfilterrule', - options={'ordering': ('priority', 'action'), 'verbose_name': 'Command filter rule'}, - ), - migrations.AlterField( - model_name='commandfilterrule', - name='priority', - field=models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - migrations.AlterField( - model_name='systemuser', - name='priority', - field=models.IntegerField(default=20, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - ] diff --git a/apps/assets/migrations/0068_auto_20210312_1455.py b/apps/assets/migrations/0068_auto_20210312_1455.py deleted file mode 100644 index 28d85ab9d..000000000 --- a/apps/assets/migrations/0068_auto_20210312_1455.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1 on 2021-03-12 06:55 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0067_auto_20210311_1113'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='priority', - field=models.IntegerField(default=81, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - ] diff --git a/apps/assets/migrations/0069_change_node_key0_to_key1.py b/apps/assets/migrations/0069_change_node_key0_to_key1.py deleted file mode 100644 index deb9b0e70..000000000 --- a/apps/assets/migrations/0069_change_node_key0_to_key1.py +++ /dev/null @@ -1,61 +0,0 @@ -from django.db import migrations -from django.db.transaction import atomic - -default_id = '00000000-0000-0000-0000-000000000002' - - -def change_key0_to_key1(apps, schema_editor): - from orgs.utils import set_current_org - - # https://stackoverflow.com/questions/28777338/django-migrations-runpython-not-able-to-call-model-methods - Organization = apps.get_model('orgs', 'Organization') - Node = apps.get_model('assets', 'Node') - - print() - org = Organization.objects.get(id=default_id) - set_current_org(org) - - exists_0 = Node.objects.filter(key__startswith='0').exists() - if not exists_0: - print(f'--> Not exist key=0 nodes, do nothing.') - return - - key_1_count = Node.objects.filter(key__startswith='1').count() - if key_1_count > 1: - print(f'--> Node key=1 have children, can`t just delete it. Please contact JumpServer team') - return - - root_node = Node.objects.filter(key='1').first() - if root_node and root_node.assets.exists(): - print(f'--> Node key=1 has assets, do nothing.') - return - - with atomic(): - if root_node: - print(f'--> Delete node key=1') - root_node.delete() - - nodes_0 = Node.objects.filter(key__startswith='0') - - for n in nodes_0: - old_key = n.key - key_list = n.key.split(':') - key_list[0] = '1' - new_key = ':'.join(key_list) - new_parent_key = ':'.join(key_list[:-1]) - n.key = new_key - n.parent_key = new_parent_key - n.save() - print('--> Modify key ( {} > {} )'.format(old_key, new_key)) - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0010_auto_20210219_1241'), - ('assets', '0068_auto_20210312_1455'), - ] - - operations = [ - migrations.RunPython(change_key0_to_key1) - ] diff --git a/apps/assets/migrations/0070_auto_20210426_1515.py b/apps/assets/migrations/0070_auto_20210426_1515.py deleted file mode 100644 index ca6ff4273..000000000 --- a/apps/assets/migrations/0070_auto_20210426_1515.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1 on 2021-04-26 07:15 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0069_change_node_key0_to_key1'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilterrule', - name='reviewers', - field=models.ManyToManyField(blank=True, related_name='review_cmd_filter_rules', to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - migrations.AlterField( - model_name='commandfilterrule', - name='action', - field=models.IntegerField(choices=[(0, 'Deny'), (1, 'Allow'), (2, 'Reconfirm')], default=0, verbose_name='Action'), - ), - ] diff --git a/apps/assets/migrations/0071_systemuser_type.py b/apps/assets/migrations/0071_systemuser_type.py deleted file mode 100644 index 9dc48fa7a..000000000 --- a/apps/assets/migrations/0071_systemuser_type.py +++ /dev/null @@ -1,104 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-04 16:46 -import uuid -from django.db import migrations, models, transaction -import django.db.models.deletion -from django.db import IntegrityError -from django.db.models import F - - -def migrate_admin_user_to_system_user(apps, schema_editor): - admin_user_model = apps.get_model("assets", "AdminUser") - system_user_model = apps.get_model("assets", "SystemUser") - db_alias = schema_editor.connection.alias - - admin_users = admin_user_model.objects.using(db_alias).all() - print() - for admin_user in admin_users: - kwargs = {} - for attr in [ - 'org_id', 'username', 'password', 'private_key', 'public_key', - 'comment', 'date_created', 'date_updated', 'created_by', - ]: - value = getattr(admin_user, attr) - kwargs[attr] = value - - name = admin_user.name - exist = system_user_model.objects.using(db_alias).filter( - name=admin_user.name, org_id=admin_user.org_id - ).exists() - if exist: - name = admin_user.name + '_' + str(admin_user.id)[:5] - - i = admin_user.id - exist = system_user_model.objects.using(db_alias).filter( - id=i, org_id=admin_user.org_id - ).exists() - if exist: - i = uuid.uuid4() - - kwargs.update({ - 'id': i, - 'name': name, - 'type': 'admin', - 'protocol': 'ssh', - 'auto_push': False, - }) - - with transaction.atomic(): - s = system_user_model(**kwargs) - try: - s.save() - except IntegrityError: - s.id = None - s.save() - print(" Migrate admin user to system user: {} => {}".format(admin_user.name, s.name)) - assets = admin_user.assets.all() - s.assets.set(assets) - - -def migrate_assets_admin_user(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - assets = asset_model.objects.using(db_alias).all() - assets.update(admin_user=F('_admin_user')) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0070_auto_20210426_1515'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='type', - field=models.CharField(choices=[('common', 'Common user'), ('admin', 'Admin user')], default='common', max_length=16, verbose_name='Type'), - ), - migrations.AlterField( - model_name='systemuser', - name='login_mode', - field=models.CharField(choices=[('auto', 'Automatic managed'), ('manual', 'Manually input')], default='auto', max_length=10, verbose_name='Login mode'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.RunPython(migrate_admin_user_to_system_user), - migrations.RenameField( - model_name='asset', - old_name='admin_user', - new_name='_admin_user', - ), - migrations.AddField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='admin_assets', to='assets.systemuser', verbose_name='Admin user'), - ), - migrations.RunPython(migrate_assets_admin_user), - migrations.RemoveField( - model_name='asset', - name='_admin_user', - ), - ] diff --git a/apps/assets/migrations/0072_historicalauthbook.py b/apps/assets/migrations/0072_historicalauthbook.py deleted file mode 100644 index e28949c1f..000000000 --- a/apps/assets/migrations/0072_historicalauthbook.py +++ /dev/null @@ -1,85 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-05 16:10 - -import common.db.fields -from django.conf import settings -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import simple_history.models -import uuid -from django.utils import timezone -from django.db import migrations, transaction - - -def migrate_old_authbook_to_history(apps, schema_editor): - authbook_model = apps.get_model("assets", "AuthBook") - history_model = apps.get_model("assets", "HistoricalAuthBook") - db_alias = schema_editor.connection.alias - - print() - while True: - authbooks = authbook_model.objects.using(db_alias).filter(is_latest=False)[:1000] - if not authbooks: - break - historys = [] - authbook_ids = [] - # Todo: 或许能优化成更新那样 - for authbook in authbooks: - authbook_ids.append(authbook.id) - history = history_model() - - for attr in [ - 'id', 'username', 'password', 'private_key', 'public_key', 'version', - 'comment', 'created_by', 'asset', 'date_created', 'date_updated' - ]: - setattr(history, attr, getattr(authbook, attr)) - history.history_type = '-' - history.history_date = timezone.now() - historys.append(history) - - with transaction.atomic(): - print(" Migrate old auth book to history table: {} items".format(len(authbook_ids))) - history_model.objects.bulk_create(historys, ignore_conflicts=True) - authbook_model.objects.filter(id__in=authbook_ids).delete() - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0071_systemuser_type'), - ] - - operations = [ - migrations.CreateModel( - name='HistoricalAuthBook', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')), - ('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')), - ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(blank=True, editable=False, verbose_name='Date created')), - ('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('is_latest', models.BooleanField(default=False, verbose_name='Latest version')), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField()), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('asset', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.asset', verbose_name='Asset')), - ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'historical AuthBook', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': 'history_date', - }, - bases=(simple_history.models.HistoricalChanges, models.Model), - ), - migrations.RunPython(migrate_old_authbook_to_history) - ] diff --git a/apps/assets/migrations/0073_auto_20210606_1142.py b/apps/assets/migrations/0073_auto_20210606_1142.py deleted file mode 100644 index ee4e214d9..000000000 --- a/apps/assets/migrations/0073_auto_20210606_1142.py +++ /dev/null @@ -1,105 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-06 03:42 - -from django.utils import timezone -from django.db import migrations, models, transaction -import django.db.models.deletion - - -def migrate_system_assets_to_authbook(apps, schema_editor): - system_user_model = apps.get_model("assets", "SystemUser") - system_user_asset_model = system_user_model.assets.through - authbook_model = apps.get_model('assets', 'AuthBook') - history_model = apps.get_model("assets", "HistoricalAuthBook") - - print() - system_users = system_user_model.objects.all() - for s in system_users: - while True: - systemuser_asset_relations = system_user_asset_model.objects.filter(systemuser=s)[:1000] - if not systemuser_asset_relations: - break - authbooks = [] - relations_ids = [] - historys = [] - for i in systemuser_asset_relations: - authbook = authbook_model(asset=i.asset, systemuser=i.systemuser, org_id=s.org_id) - authbooks.append(authbook) - relations_ids.append(i.id) - - history = history_model( - asset=i.asset, systemuser=i.systemuser, - date_created=timezone.now(), date_updated=timezone.now(), - ) - history.history_type = '-' - history.history_date = timezone.now() - historys.append(history) - - with transaction.atomic(): - print(" Migrate system user assets relations: {} items".format(len(relations_ids))) - authbook_model.objects.bulk_create(authbooks, ignore_conflicts=True) - history_model.objects.bulk_create(historys) - system_user_asset_model.objects.filter(id__in=relations_ids).delete() - - -def migrate_authbook_secret_to_system_user(apps, schema_editor): - authbook_model = apps.get_model('assets', 'AuthBook') - history_model = apps.get_model('assets', 'HistoricalAuthBook') - - print() - authbooks_without_systemuser = authbook_model.objects.filter(systemuser__isnull=True) - for authbook in authbooks_without_systemuser: - matched = authbook_model.objects.filter( - asset=authbook.asset, systemuser__username=authbook.username - ) - if not matched: - continue - historys = [] - for i in matched: - history = history_model( - asset=i.asset, systemuser=i.systemuser, - date_created=timezone.now(), date_updated=timezone.now(), - version=authbook.version - ) - history.history_type = '-' - history.history_date = timezone.now() - historys.append(history) - - with transaction.atomic(): - print(" Migrate secret to system user assets account: {} items".format(len(historys))) - matched.update(password=authbook.password, private_key=authbook.private_key, - public_key=authbook.public_key, version=authbook.version) - history_model.objects.bulk_create(historys) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0072_historicalauthbook'), - ] - - operations = [ - migrations.AddField( - model_name='authbook', - name='systemuser', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.systemuser', verbose_name='System user'), - ), - migrations.AddField( - model_name='historicalauthbook', - name='systemuser', - field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.systemuser', verbose_name='System user'), - ), - migrations.AlterUniqueTogether( - name='authbook', - unique_together={('username', 'asset', 'systemuser')}, - ), - migrations.RunPython(migrate_system_assets_to_authbook), - migrations.RunPython(migrate_authbook_secret_to_system_user), - migrations.RemoveField( - model_name='authbook', - name='is_latest', - ), - migrations.RemoveField( - model_name='historicalauthbook', - name='is_latest', - ), - ] diff --git a/apps/assets/migrations/0074_remove_systemuser_assets.py b/apps/assets/migrations/0074_remove_systemuser_assets.py deleted file mode 100644 index 250c31b34..000000000 --- a/apps/assets/migrations/0074_remove_systemuser_assets.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-06 03:40 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0073_auto_20210606_1142'), - ] - - operations = [ - migrations.RemoveField( - model_name='systemuser', - name='assets', - ), - - migrations.AddField( - model_name='systemuser', - name='assets', - field=models.ManyToManyField(blank=True, related_name='system_users', through='assets.AuthBook', to='assets.Asset', verbose_name='Assets'), - ), - ] diff --git a/apps/assets/migrations/0075_auto_20210705_1759.py b/apps/assets/migrations/0075_auto_20210705_1759.py deleted file mode 100644 index 686d61bf0..000000000 --- a/apps/assets/migrations/0075_auto_20210705_1759.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 3.1 on 2021-07-05 09:59 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0074_remove_systemuser_assets'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='connectivity', - field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), - ), - migrations.AddField( - model_name='asset', - name='date_verified', - field=models.DateTimeField(null=True, verbose_name='Date verified'), - ), - migrations.AddField( - model_name='authbook', - name='connectivity', - field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), - ), - migrations.AddField( - model_name='authbook', - name='date_verified', - field=models.DateTimeField(null=True, verbose_name='Date verified'), - ), - migrations.AddField( - model_name='historicalauthbook', - name='connectivity', - field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), - ), - migrations.AddField( - model_name='historicalauthbook', - name='date_verified', - field=models.DateTimeField(null=True, verbose_name='Date verified'), - ), - migrations.AlterField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='gateway', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0076_delete_assetuser.py b/apps/assets/migrations/0076_delete_assetuser.py deleted file mode 100644 index 75fdebd7f..000000000 --- a/apps/assets/migrations/0076_delete_assetuser.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.1.6 on 2021-07-12 02:25 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0075_auto_20210705_1759'), - ] - - operations = [ - migrations.DeleteModel( - name='AssetUser', - ), - ] diff --git a/apps/assets/migrations/0077_auto_20211012_1642.py b/apps/assets/migrations/0077_auto_20211012_1642.py deleted file mode 100644 index 6c56917e0..000000000 --- a/apps/assets/migrations/0077_auto_20211012_1642.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.12 on 2021-10-12 08:42 - -from django.db import migrations - - -def migrate_platform_win2016(apps, schema_editor): - platform_model = apps.get_model("assets", "Platform") - win2016 = platform_model.objects.filter(name='Windows2016').first() - if not win2016: - print("Error: Not found Windows2016 platform") - return - win2016.meta = {"security": "any"} - win2016.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0076_delete_assetuser'), - ] - - operations = [ - migrations.RunPython(migrate_platform_win2016) - ] diff --git a/apps/assets/migrations/0078_auto_20211014_2209.py b/apps/assets/migrations/0078_auto_20211014_2209.py deleted file mode 100644 index b2c1cf371..000000000 --- a/apps/assets/migrations/0078_auto_20211014_2209.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.1.13 on 2021-10-14 14:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0077_auto_20211012_1642'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='authbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='historicalauthbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0079_auto_20211102_1922.py b/apps/assets/migrations/0079_auto_20211102_1922.py deleted file mode 100644 index 592df0259..000000000 --- a/apps/assets/migrations/0079_auto_20211102_1922.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-02 11:22 - -from django.db import migrations - - -def create_internal_platform(apps, schema_editor): - model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - type_platforms = ( - ('Windows-RDP', 'Windows', {'security': 'rdp'}), - ('Windows-TLS', 'Windows', {'security': 'tls'}), - ) - for name, base, meta in type_platforms: - defaults = {'name': name, 'base': base, 'meta': meta, 'internal': True} - model.objects.using(db_alias).update_or_create( - name=name, defaults=defaults - ) - - win2016 = model.objects.filter(name='Windows2016').first() - if win2016: - win2016.internal = False - win2016.save(update_fields=['internal']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0078_auto_20211014_2209'), - ] - - operations = [ - migrations.RunPython(create_internal_platform) - ] diff --git a/apps/assets/migrations/0080_auto_20211104_1347.py b/apps/assets/migrations/0080_auto_20211104_1347.py deleted file mode 100644 index 75210149e..000000000 --- a/apps/assets/migrations/0080_auto_20211104_1347.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.13 on 2021-11-04 05:47 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0079_auto_20211102_1922'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='su_enabled', - field=models.BooleanField(default=False, verbose_name='User switch'), - ), - migrations.AddField( - model_name='systemuser', - name='su_from', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='assets.systemuser', verbose_name='Switch from'), - ), - ] diff --git a/apps/assets/migrations/0081_auto_20211105_1605.py b/apps/assets/migrations/0081_auto_20211105_1605.py deleted file mode 100644 index 08e055617..000000000 --- a/apps/assets/migrations/0081_auto_20211105_1605.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-05 08:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0080_auto_20211104_1347'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0082_auto_20211209_1440.py b/apps/assets/migrations/0082_auto_20211209_1440.py deleted file mode 100644 index a0576fe13..000000000 --- a/apps/assets/migrations/0082_auto_20211209_1440.py +++ /dev/null @@ -1,74 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-09 06:40 - -from django.conf import settings -from django.db import migrations, models - - -def migrate_system_users_cmd_filters(apps, schema_editor): - system_user_model = apps.get_model("assets", "SystemUser") - cmd_filter_model = apps.get_model("assets", "CommandFilter") - su_through = system_user_model.cmd_filters.through - cf_through = cmd_filter_model.system_users.through - - su_relation_objects = su_through.objects.all() - cf_relation_objects = [ - cf_through(**{ - 'id': su_relation.id, - 'systemuser_id': su_relation.systemuser_id, - 'commandfilter_id': su_relation.commandfilter_id - }) - for su_relation in su_relation_objects - ] - cf_through.objects.bulk_create(cf_relation_objects) - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0014_auto_20211105_1605'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0081_auto_20211105_1605'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilter', - name='applications', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='applications.Application', verbose_name='Application'), - ), - migrations.AddField( - model_name='commandfilter', - name='assets', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='assets.Asset', verbose_name='Asset'), - ), - migrations.AddField( - model_name='commandfilter', - name='system_users', - field=models.ManyToManyField(blank=True, related_name='cmd_filters_pre', to='assets.SystemUser', verbose_name='System user'), - ), - migrations.AddField( - model_name='commandfilter', - name='users', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AddField( - model_name='commandfilter', - name='user_groups', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='users.UserGroup', verbose_name='User group'), - ), - migrations.AlterField( - model_name='systemuser', - name='cmd_filters', - field=models.ManyToManyField(blank=True, related_name='system_users_bak', to='assets.CommandFilter', verbose_name='Command filter'), - ), - migrations.RunPython(migrate_system_users_cmd_filters), - migrations.RemoveField( - model_name='systemuser', - name='cmd_filters', - ), - migrations.AlterField( - model_name='commandfilter', - name='system_users', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='assets.SystemUser', verbose_name='System user'), - ), - ] diff --git a/apps/assets/migrations/0083_auto_20211215_1436.py b/apps/assets/migrations/0083_auto_20211215_1436.py deleted file mode 100644 index f3bde1ec9..000000000 --- a/apps/assets/migrations/0083_auto_20211215_1436.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-15 06:36 - -from django.db import migrations, models - -OLD_ACTION_ALLOW = 1 -NEW_ACTION_ALLOW = 9 - - -def migrate_action(apps, schema_editor): - model = apps.get_model("assets", "CommandFilterRule") - model.objects.filter(action=OLD_ACTION_ALLOW).update(action=NEW_ACTION_ALLOW) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0082_auto_20211209_1440'), - ] - - operations = [ - migrations.RunPython(migrate_action), - migrations.AlterField( - model_name='commandfilterrule', - name='action', - field=models.IntegerField(choices=[(0, 'Deny'), (9, 'Allow'), (2, 'Reconfirm')], default=0, verbose_name='Action'), - ), - ] diff --git a/apps/assets/migrations/0084_auto_20220112_1959.py b/apps/assets/migrations/0084_auto_20220112_1959.py deleted file mode 100644 index 25aedef77..000000000 --- a/apps/assets/migrations/0084_auto_20220112_1959.py +++ /dev/null @@ -1,62 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-12 11:59 - -import common.db.encoder -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0083_auto_20211215_1436'), - ] - - operations = [ - migrations.CreateModel( - name='AccountBackupPlan', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic perform')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('types', models.IntegerField(choices=[(255, 'All'), (1, 'Asset'), (2, 'Application')], default=255, verbose_name='Type')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('recipients', models.ManyToManyField(blank=True, related_name='recipient_escape_route_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), - ], - options={ - 'verbose_name': 'Account backup plan', - 'ordering': ['name'], - 'unique_together': {('name', 'org_id')}, - }, - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('redis', 'Redis'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.CreateModel( - name='AccountBackupPlanExecution', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')), - ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), - ('plan_snapshot', models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Account backup snapshot')), - ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), - ('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')), - ('is_success', models.BooleanField(default=False, verbose_name='Is success')), - ('plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution', to='assets.accountbackupplan', verbose_name='Account backup plan')), - ], - options={ - 'verbose_name': 'Account backup execution', - }, - ), - ] diff --git a/apps/assets/migrations/0085_commandfilterrule_ignore_case.py b/apps/assets/migrations/0085_commandfilterrule_ignore_case.py deleted file mode 100644 index b1289b7c5..000000000 --- a/apps/assets/migrations/0085_commandfilterrule_ignore_case.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-08 02:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0084_auto_20220112_1959'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilterrule', - name='ignore_case', - field=models.BooleanField(default=True, verbose_name='Ignore case'), - ), - ] diff --git a/apps/assets/migrations/0086_auto_20220217_2135.py b/apps/assets/migrations/0086_auto_20220217_2135.py deleted file mode 100644 index fcdb9e0c8..000000000 --- a/apps/assets/migrations/0086_auto_20220217_2135.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0085_commandfilterrule_ignore_case'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'permissions': [('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset')], 'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='authbook', - options={'permissions': [('view_assetaccountsecret', 'Can view asset account secret'), ('change_assetaccountsecret', 'Can change asset account secret')], 'verbose_name': 'AuthBook'}, - ), - migrations.AlterModelOptions( - name='label', - options={'verbose_name': 'Label'}, - ), - ] diff --git a/apps/assets/migrations/0087_auto_20220223_1539.py b/apps/assets/migrations/0087_auto_20220223_1539.py deleted file mode 100644 index cf707a495..000000000 --- a/apps/assets/migrations/0087_auto_20220223_1539.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-23 07:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0086_auto_20220217_2135'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0088_auto_20220303_1612.py b/apps/assets/migrations/0088_auto_20220303_1612.py deleted file mode 100644 index f0b0191e1..000000000 --- a/apps/assets/migrations/0088_auto_20220303_1612.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-03 08:12 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0087_auto_20220223_1539'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset'), ('match_asset', 'Can match asset')], 'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='node', - options={'ordering': ['parent_key', 'value'], 'permissions': [('match_node', 'Can match node')], 'verbose_name': 'Node'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'permissions': [('match_systemuser', 'Can match system user')], 'verbose_name': 'System user'}, - ), - ] diff --git a/apps/assets/migrations/0089_auto_20220310_0616.py b/apps/assets/migrations/0089_auto_20220310_0616.py deleted file mode 100644 index 1aa70d616..000000000 --- a/apps/assets/migrations/0089_auto_20220310_0616.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-09 22:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0088_auto_20220303_1612'), - ] - - operations = [ - migrations.AlterModelOptions( - name='authbook', - options={'permissions': [('test_authbook', 'Can test asset account connectivity'), ('view_assetaccountsecret', 'Can view asset account secret'), ('change_assetaccountsecret', 'Can change asset account secret')], 'verbose_name': 'AuthBook'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'permissions': [('match_systemuser', 'Can match system user')], 'verbose_name': 'System user'}, - ), - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='gateway', - options={'permissions': [('test_gateway', 'Test gateway')], 'verbose_name': 'Gateway'}, - ), - ] diff --git a/apps/assets/migrations/0090_auto_20220412_1145.py b/apps/assets/migrations/0090_auto_20220412_1145.py deleted file mode 100644 index 3259cd37b..000000000 --- a/apps/assets/migrations/0090_auto_20220412_1145.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-12 03:45 - -from django.db import migrations, models - - -def create_internal_platform(apps, schema_editor): - model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - type_platforms = ( - ('AIX', 'Unix', None), - ) - for name, base, meta in type_platforms: - defaults = {'name': name, 'base': base, 'meta': meta, 'internal': True} - model.objects.using(db_alias).update_or_create( - name=name, defaults=defaults - ) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0089_auto_20220310_0616'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='number', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Asset number'), - ), - migrations.RunPython(create_internal_platform) - ] diff --git a/apps/assets/migrations/0091_auto_20220629_1826.py b/apps/assets/migrations/0091_auto_20220629_1826.py deleted file mode 100644 index 589dce2b2..000000000 --- a/apps/assets/migrations/0091_auto_20220629_1826.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-29 10:26 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0090_auto_20220412_1145'), - ] - - operations = [ - migrations.AlterModelOptions( - name='authbook', - options={'permissions': [('test_authbook', 'Can test asset account connectivity'), ('view_assetaccountsecret', 'Can view asset account secret'), ('change_assetaccountsecret', 'Can change asset account secret'), ('view_assethistoryaccount', 'Can view asset history account'), ('view_assethistoryaccountsecret', 'Can view asset history account secret')], 'verbose_name': 'AuthBook'}, - ), - migrations.AlterModelOptions( - name='historicalauthbook', - options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical AuthBook', 'verbose_name_plural': 'historical AuthBooks'}, - ), - migrations.AlterField( - model_name='historicalauthbook', - name='history_date', - field=models.DateTimeField(db_index=True), - ), - ] diff --git a/apps/assets/migrations/0092_commandfilter_nodes.py b/apps/assets/migrations/0092_commandfilter_nodes.py deleted file mode 100644 index b3c1916e3..000000000 --- a/apps/assets/migrations/0092_commandfilter_nodes.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.15 on 2022-10-09 09:55 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0091_auto_20220629_1826'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilter', - name='nodes', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='assets.Node', verbose_name='Nodes'), - ), - ] diff --git a/apps/assets/migrations/0093_auto_20220403_1627.py b/apps/assets/migrations/0093_auto_20220403_1627.py deleted file mode 100644 index 484da9740..000000000 --- a/apps/assets/migrations/0093_auto_20220403_1627.py +++ /dev/null @@ -1,193 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-02 08:27 - -import django.db -from django.db import migrations, models - -import common.db.fields - - -def migrate_to_host(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - host_model = apps.get_model("assets", 'Host') - db_alias = schema_editor.connection.alias - - count = 0 - batch_size = 1000 - - while True: - assets = asset_model.objects.using(db_alias).all()[count:count + batch_size] - if not assets: - break - count += len(assets) - hosts = [host_model(asset_ptr=asset) for asset in assets] - host_model.objects.using(db_alias).bulk_create(hosts, ignore_conflicts=True) - - -def migrate_hardware_info(apps, *args): - asset_model = apps.get_model("assets", "Asset") - - count = 0 - batch_size = 1000 - hardware_fields = [ - 'vendor', 'model', 'sn', 'cpu_model', 'cpu_count', 'cpu_cores', - 'cpu_vcpus', 'memory', 'disk_total', 'disk_info', 'os', 'os_arch', - 'os_version', 'hostname_raw', 'number' - ] - - while True: - assets = asset_model.objects.all()[count:count + batch_size] - if not assets: - break - count += len(assets) - - updated = [] - for asset in assets: - info = {field: getattr(asset, field) for field in hardware_fields if getattr(asset, field)} - if not info: - continue - asset.info = info - updated.append(asset) - asset_model.objects.bulk_update(updated, ['info']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0092_commandfilter_nodes'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='info', - field=models.JSONField(blank=True, default=dict, verbose_name='Info'), - ), - migrations.RenameField( - model_name='asset', - old_name='hostname', - new_name='name', - ), - migrations.AlterField( - model_name='asset', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterModelOptions( - name='asset', - options={ - 'ordering': ['name'], - 'permissions': [ - ('refresh_assethardwareinfo', 'Can refresh asset hardware info'), - ('test_assetconnectivity', 'Can test asset connectivity'), - ('push_assetaccount', 'Can push account to asset'), - ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), - ('add_assettonode', 'Add asset to node'), - ('move_assettonode', 'Move asset to node') - ], - 'verbose_name': 'Asset' - }, - ), - migrations.RenameField( - model_name='asset', - old_name='ip', - new_name='address', - ), - migrations.AlterField( - model_name='asset', - name='address', - field=models.CharField(db_index=True, max_length=767, verbose_name='Address'), - ), - migrations.AddField( - model_name='asset', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='asset', - name='updated_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='asset', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - migrations.CreateModel( - name='Host', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'verbose_name': 'Host', - }, - ), - migrations.CreateModel( - name='Database', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ('db_name', models.CharField(blank=True, max_length=1024, verbose_name='Database')), - ('allow_invalid_cert', models.BooleanField(default=False, verbose_name='Allow invalid cert')), - ('ca_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='CA cert')), - ('client_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='Client cert')), - ('client_key', common.db.fields.EncryptTextField(blank=True, verbose_name='Client key'),), - ('use_ssl', models.BooleanField(default=False, verbose_name='Use SSL'),), - ], - options={ - 'verbose_name': 'Database', - }, - bases=('assets.asset',), - ), - migrations.CreateModel( - name='Device', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Device', - }, - bases=('assets.asset',), - ), - migrations.CreateModel( - name='Cloud', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Cloud', - }, - bases=('assets.asset',), - ), - migrations.CreateModel( - name='Web', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ('autofill', models.CharField(choices=[('no', 'Disabled'), ('basic', 'Basic'), ('script', 'Script')], - default='basic', max_length=16, verbose_name='Autofill')), - ('password_selector', - models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')), - ('submit_selector', - models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')), - ('username_selector', - models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')), - ('script', models.JSONField(blank=True, default=list, verbose_name='Script')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Web', - }, - bases=('assets.asset',), - ), - migrations.RunPython(migrate_hardware_info), - migrations.RunPython(migrate_to_host), - ] diff --git a/apps/assets/migrations/0094_auto_20220402_1736.py b/apps/assets/migrations/0094_auto_20220402_1736.py deleted file mode 100644 index daf53270b..000000000 --- a/apps/assets/migrations/0094_auto_20220402_1736.py +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-02 09:36 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0093_auto_20220403_1627'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='cpu_cores', - ), - migrations.RemoveField( - model_name='asset', - name='cpu_count', - ), - migrations.RemoveField( - model_name='asset', - name='cpu_model', - ), - migrations.RemoveField( - model_name='asset', - name='cpu_vcpus', - ), - migrations.RemoveField( - model_name='asset', - name='disk_info', - ), - migrations.RemoveField( - model_name='asset', - name='disk_total', - ), - migrations.RemoveField( - model_name='asset', - name='hostname_raw', - ), - migrations.RemoveField( - model_name='asset', - name='memory', - ), - migrations.RemoveField( - model_name='asset', - name='model', - ), - migrations.RemoveField( - model_name='asset', - name='os', - ), - migrations.RemoveField( - model_name='asset', - name='os_arch', - ), - migrations.RemoveField( - model_name='asset', - name='os_version', - ), - migrations.RemoveField( - model_name='asset', - name='sn', - ), - migrations.RemoveField( - model_name='asset', - name='vendor', - ), - ] diff --git a/apps/assets/migrations/0095_auto_20220407_1726.py b/apps/assets/migrations/0095_auto_20220407_1726.py deleted file mode 100644 index fa0798a20..000000000 --- a/apps/assets/migrations/0095_auto_20220407_1726.py +++ /dev/null @@ -1,51 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-07 09:26 - -from django.db import migrations, models - - -def migrate_platform_type_to_lower(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - platforms = platform_model.objects.all() - for p in platforms: - p.type = p.type.lower() - p.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0094_auto_20220402_1736'), - ] - - operations = [ - migrations.RenameField( - model_name='platform', - old_name='base', - new_name='type', - ), - migrations.AddField( - model_name='platform', - name='category', - field=models.CharField(default='host', max_length=32, verbose_name='Category'), - ), - migrations.AlterField( - model_name='platform', - name='type', - field=models.CharField(default='linux', max_length=32, verbose_name='Type'), - ), - migrations.AddField( - model_name='platform', - name='domain_enabled', - field=models.BooleanField(default=True, verbose_name='Domain enabled'), - ), - migrations.AddField( - model_name='platform', - name='su_enabled', - field=models.BooleanField(default=False, verbose_name='Su enabled'), - ), - migrations.AddField( - model_name='platform', - name='su_method', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Su method'), - ), - migrations.RunPython(migrate_platform_type_to_lower) - ] diff --git a/apps/assets/migrations/0096_auto_20220426_1550.py b/apps/assets/migrations/0096_auto_20220426_1550.py deleted file mode 100644 index 274a22331..000000000 --- a/apps/assets/migrations/0096_auto_20220426_1550.py +++ /dev/null @@ -1,57 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-26 07:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0095_auto_20220407_1726'), - ] - - operations = [ - migrations.CreateModel( - name='PlatformProtocol', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=32, verbose_name='Name')), - ('port', models.IntegerField(verbose_name='Port')), - ('setting', models.JSONField(default=dict, verbose_name='Setting')), - ('platform', - models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='protocols', to='assets.platform'),), - ('default', models.BooleanField(default=True, verbose_name='Default')), - ('required', models.BooleanField(default=False, verbose_name='Required')), - ], - ), - migrations.CreateModel( - name='PlatformAutomation', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ansible_enabled', models.BooleanField(default=False, verbose_name='Enabled')), - ('ansible_config', models.JSONField(default=dict, verbose_name='Ansible config')), - ('ping_enabled', models.BooleanField(default=False, verbose_name='Ping enabled')), - ('ping_method', models.CharField(blank=True, max_length=32, null=True, verbose_name='Ping method')), - ('gather_facts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), - ('gather_facts_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), - ('change_secret_enabled', models.BooleanField(default=False, verbose_name='Change secret enabled')), - ('change_secret_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Change secret method')), - ('push_account_enabled', models.BooleanField(default=False, verbose_name='Push account enabled')), - ('push_account_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Push account method')), - ('verify_account_enabled', models.BooleanField(default=False, verbose_name='Verify account enabled')), - ('verify_account_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Verify account method')), - ('gather_accounts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), - ('gather_accounts_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), - ], - ), - migrations.AddField( - model_name='platform', - name='automation', - field=models.OneToOneField(blank=True, null=True, on_delete=models.deletion.CASCADE, - related_name='platform', to='assets.platformautomation', - verbose_name='Automation'), - ), - ] diff --git a/apps/assets/migrations/0097_auto_20220426_1558.py b/apps/assets/migrations/0097_auto_20220426_1558.py deleted file mode 100644 index 3fdf648a1..000000000 --- a/apps/assets/migrations/0097_auto_20220426_1558.py +++ /dev/null @@ -1,1243 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-26 07:58 - -import json - -from django.db import migrations - -from assets.const import AllTypes - -platforms_data_json = '''[ - { - "category": "host", - "type": "linux", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "Linux", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "linux", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "Gateway", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "Unix", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "macOS", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "BSD", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "AIX", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_aix", - "push_account_method": "push_account_aix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Windows", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": false, - "default": false - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Windows-TLS", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "tls" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": false, - "default": false - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Windows-RDP", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "rdp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": false, - "default": false - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "RemoteAppHost", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": true, - "default": false - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "General", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Cisco", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Huawei", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "H3C", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "mysql", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "MySQL", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "mysql_ping", - "gather_accounts_method": "gather_accounts_mysql", - "verify_account_method": "verify_account_mysql", - "change_secret_method": "change_secret_mysql", - "push_account_method": "push_account_mysql" - }, - "protocols": [ - { - "name": "mysql", - "port": 3306, - "setting": {}, - "required": false, - "primary": true, - "default": false - } - ] - }, - { - "category": "database", - "type": "mariadb", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "MariaDB", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "mysql_ping", - "gather_accounts_method": "gather_accounts_mysql", - "verify_account_method": "verify_account_mysql", - "change_secret_method": "change_secret_mysql", - "push_account_method": "push_account_mysql" - }, - "protocols": [ - { - "name": "mariadb", - "port": 3306, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "postgresql", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "PostgreSQL", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "ping_postgresql", - "gather_accounts_method": "gather_accounts_postgresql", - "verify_account_method": "verify_account_postgresql", - "change_secret_method": "change_secret_postgresql", - "push_account_method": "push_account_postgresql" - }, - "protocols": [ - { - "name": "postgresql", - "port": 5432, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "oracle", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Oracle", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "oracle_ping", - "gather_accounts_method": "gather_accounts_oracle", - "verify_account_method": "verify_account_oracle", - "change_secret_method": "change_secret_oracle", - "push_account_method": "push_account_oracle" - }, - "protocols": [ - { - "name": "oracle", - "port": 1521, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "sqlserver", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "SQLServer", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "sqlserver_ping", - "verify_account_method": "verify_account_sqlserver", - "change_secret_method": "change_secret_sqlserver", - "push_account_method": "push_account_sqlserver" - }, - "protocols": [ - { - "name": "sqlserver", - "port": 1433, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "clickhouse", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "ClickHouse", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "clickhouse", - "port": 9000, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "mongodb", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "MongoDB", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "mongodb_ping", - "gather_accounts_method": "gather_accounts_mongodb", - "verify_account_method": "verify_account_mongodb", - "change_secret_method": "change_secret_mongodb", - "push_account_method": "push_account_mongodb" - }, - "protocols": [ - { - "name": "mongodb", - "port": 27017, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "redis", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Redis", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "redis", - "port": 6379, - "required": false, - "setting": { - "auth_username": false - }, - "primary": true, - "default": false - } - ] - }, - { - "category": "database", - "type": "redis", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Redis6+", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "redis", - "port": 6379, - "required": false, - "setting": { - "auth_username": true - }, - "primary": true, - "default": false - } - ] - }, - { - "category": "web", - "type": "website", - "internal": true, - "charset": "utf-8", - "domain_enabled": false, - "su_enabled": false, - "name": "Website", - "automation": { - "ansible_enabled": false, - "ping_enabled": false, - "gather_facts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false, - "gather_accounts_enabled": false - }, - "protocols": [ - { - "name": "http", - "port": 80, - "setting": { - "username_selector": "name=username", - "password_selector": "name=password", - "submit_selector": "id=longin_button" - }, - "primary": true, - "required": false, - "default": false - } - ] - }, - { - "category": "cloud", - "type": "private", - "internal": true, - "charset": "utf-8", - "domain_enabled": false, - "su_enabled": false, - "name": "Vmware-vSphere", - "automation": { - "ansible_enabled": false, - "ansible_config": {}, - "gather_facts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false, - "gather_accounts_enabled": false - }, - "protocols": [ - { - "name": "http", - "port": 80, - "setting": { - "username_selector": "name=username", - "password_selector": "name=password", - "submit_selector": "id=longin_button" - }, - "primary": true, - "required": false, - "default": false - } - ] - }, - { - "category": "cloud", - "type": "k8s", - "internal": true, - "charset": "utf-8", - "domain_enabled": false, - "su_enabled": false, - "name": "Kubernetes", - "automation": { - "ansible_enabled": false, - "ansible_config": {}, - "gather_facts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false, - "gather_accounts_enabled": false - }, - "protocols": [ - { - "name": "k8s", - "port": 443, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - } -]''' - - -def create_internal_platforms(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - platforms_data = json.loads(platforms_data_json) - - for platform_data in platforms_data: - protocols = platform_data.pop('protocols', []) - platform_data['protocols'] = [p for p in protocols if p.pop('primary', True) is not None] - AllTypes.create_or_update_by_platform_data(platform_data, platform_cls=platform_cls) - - -def update_user_platforms(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - AllTypes.update_user_create_platforms(platform_cls) - - -def migrate_macos_platform(apps, schema_editor): - db_alias = schema_editor.connection.alias - asset_model = apps.get_model('assets', 'Asset') - platform_model = apps.get_model('assets', 'Platform') - old_macos = platform_model.objects.using(db_alias).filter( - name='MacOS', type='macos' - ).first() - new_macos = platform_model.objects.using(db_alias).filter( - name='macOS', type='unix' - ).first() - - if not old_macos or not new_macos: - return - - asset_model.objects.using(db_alias).filter( - platform=old_macos - ).update(platform=new_macos) - - platform_model.objects.using(db_alias).filter(id=old_macos.id).delete() - - -def migrate_connectivity(apps, schema_editor): - db_alias = schema_editor.connection.alias - asset_model = apps.get_model('assets', 'Asset') - asset_model.objects.using(db_alias).filter(connectivity='unknown').update(connectivity='-') - asset_model.objects.using(db_alias).filter(connectivity='failed').update(connectivity='err') - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0096_auto_20220426_1550'), - ] - - operations = [ - migrations.RunPython(create_internal_platforms), - migrations.RunPython(update_user_platforms), - migrations.RunPython(migrate_macos_platform), - migrations.RunPython(migrate_connectivity), - ] diff --git a/apps/assets/migrations/0098_auto_20220430_2126.py b/apps/assets/migrations/0098_auto_20220430_2126.py deleted file mode 100644 index 9abbea40b..000000000 --- a/apps/assets/migrations/0098_auto_20220430_2126.py +++ /dev/null @@ -1,171 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-26 07:58 -import uuid - -from django.db import migrations - -failed_apps = [] - - -def get_prop_name_id(apps, app, category): - asset_model = apps.get_model('assets', 'Asset') - _id = app.id - id_exists = asset_model.objects.filter(id=_id).exists() - if id_exists: - _id = uuid.uuid4() - name = app.name - name_exists = asset_model.objects.filter(name=name).exists() - if name_exists: - name = category + '-' + app.name - return _id, name - - -def migrate_database_to_asset(apps, *args): - node_model = apps.get_model('assets', 'Node') - app_model = apps.get_model('applications', 'Application') - db_model = apps.get_model('assets', 'Database') - platform_model = apps.get_model('assets', 'Platform') - - applications = app_model.objects.filter(category='db') - platforms = platform_model.objects.all().filter(internal=True).exclude(name='Redis6+') - platforms_map = {p.type: p for p in platforms} - print() - - for app in applications: - attrs = {'host': '', 'port': 0, 'database': ''} - _attrs = app.attrs or {} - attrs.update(_attrs) - - name = 'DB-{}'.format(app.name) - db = db_model( - id=app.id, name=name, address=attrs['host'], - protocols='{}/{}'.format(app.type, attrs['port']), - db_name=attrs['database'] or '', - platform=platforms_map[app.type], - org_id=app.org_id - ) - try: - print("\t- Create database: ", app.name) - db.save() - except: - failed_apps.append(app) - pass - - -def migrate_cloud_to_asset(apps, *args): - app_model = apps.get_model('applications', 'Application') - cloud_model = apps.get_model('assets', 'Cloud') - platform_model = apps.get_model('assets', 'Platform') - - applications = app_model.objects.filter(category='cloud') - platform = platform_model.objects.filter(type='k8s').first() - print() - - for app in applications: - attrs = app.attrs - print("\t- Create cloud: {}".format(app.name)) - name = 'Cloud-{}'.format(app.name) - cloud = cloud_model( - id=app.id, name=name, - address=attrs.get('cluster', ''), - protocols='k8s/443', platform=platform, - org_id=app.org_id, - ) - - try: - cloud.save() - except Exception as e: - failed_apps.append(cloud) - print("Error: ", e) - - -def create_app_nodes(apps, org_id): - node_model = apps.get_model('assets', 'Node') - - child_pattern = r'^[0-9]+:[0-9]+$' - node_keys = node_model.objects.filter(org_id=org_id) \ - .filter(key__regex=child_pattern) \ - .values_list('key', flat=True) - if node_keys: - node_key_split = [key.split(':') for key in node_keys] - next_value = max([int(k[1]) for k in node_key_split]) + 1 - parent_key = node_key_split[0][0] - else: - root_node = node_model.objects.filter(org_id=org_id) \ - .filter(parent_key='', key__regex=r'^[0-9]+$') \ - .exclude(key__startswith='-') \ - .first() - if not root_node: - return - parent_key = root_node.key - next_value = 0 - - next_key = '{}:{}'.format(parent_key, next_value) - name = 'Apps' - parent = node_model.objects.get(key=parent_key) - full_value = parent.full_value + '/' + name - defaults = { - 'key': next_key, 'value': name, 'parent_key': parent_key, - 'full_value': full_value, 'org_id': org_id - } - node, __ = node_model.objects.get_or_create( - defaults=defaults, value=name, org_id=org_id, - parent_key=parent_key - ) - node.parent = parent - return node - - -def migrate_to_nodes(apps, *args): - org_model = apps.get_model('orgs', 'Organization') - asset_model = apps.get_model('assets', 'Asset') - orgs = org_model.objects.all() - - # Todo: 优化一些 - for org in orgs: - node = create_app_nodes(apps, org.id) - assets = asset_model.objects.filter( - platform__category__in=['remote_app', 'database', 'cloud'], - org_id=org.id - ) - if not node: - continue - print("\t- Set node asset: ", node) - node.assets_amount = len(assets) - node.save() - node.assets.set(assets) - parent = node.parent - parent.assets_amount += len(assets) - parent.save() - - -def migrate_ori_host_to_devices(apps, *args): - device_model = apps.get_model('assets', 'Device') - asset_model = apps.get_model('assets', 'Asset') - host_model = apps.get_model('assets', 'Host') - hosts_need_migrate_to_device = host_model.objects.filter(asset_ptr__platform__category='device') - assets = asset_model.objects.filter(id__in=hosts_need_migrate_to_device.values_list('asset_ptr_id', flat=True)) - assets_map = {asset.id: asset for asset in assets} - - print("\t- Migrate ori host to device: ", len(hosts_need_migrate_to_device)) - for host in hosts_need_migrate_to_device: - asset = assets_map.get(host.asset_ptr_id) - if not asset: - continue - device = device_model(asset_ptr_id=asset.id) - device.__dict__.update(asset.__dict__) - device.save() - host.delete(keep_parents=True) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0097_auto_20220426_1558'), - ('applications', '0020_auto_20220316_2028') - ] - - operations = [ - migrations.RunPython(migrate_database_to_asset), - migrations.RunPython(migrate_cloud_to_asset), - migrations.RunPython(migrate_to_nodes), - migrations.RunPython(migrate_ori_host_to_devices), - ] diff --git a/apps/assets/migrations/0099_auto_20220711_1409.py b/apps/assets/migrations/0099_auto_20220711_1409.py deleted file mode 100644 index c0444048f..000000000 --- a/apps/assets/migrations/0099_auto_20220711_1409.py +++ /dev/null @@ -1,71 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-11 08:59 - -import time - -from django.conf import settings -from django.db import migrations, models - - -def migrate_asset_protocols(apps, schema_editor): - asset_model = apps.get_model('assets', 'Asset') - protocol_model = apps.get_model('assets', 'Protocol') - - count = 0 - bulk_size = 1000 - print("\n\tStart migrate asset protocols") - while True: - start = time.time() - assets = asset_model.objects.all()[count:count + bulk_size] - if not assets: - break - count += len(assets) - assets_protocols = [] - - for asset in assets: - old_protocols = asset._protocols or '{}/{}'.format(asset.protocol, asset.port) or 'ssh/22' - - if ',' in old_protocols: - _protocols = old_protocols.split(',') - else: - _protocols = old_protocols.split() - - for name_port in _protocols: - name_port_list = name_port.split('/') - if len(name_port_list) != 2: - continue - - name, port = name_port_list - protocol = protocol_model(**{'name': name, 'port': port, 'asset': asset}) - assets_protocols.append(protocol) - - protocol_model.objects.bulk_create(assets_protocols, ignore_conflicts=True) - print("\t - Create asset protocols: {}-{} using: {:.2f}s".format( - count - len(assets), count, time.time() - start - )) - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0098_auto_20220430_2126'), - ] - - operations = [ - migrations.RenameField( - model_name='asset', - old_name='protocols', - new_name='_protocols', - ), - migrations.CreateModel( - name='Protocol', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=32, verbose_name='Name')), - ('port', models.IntegerField(verbose_name='Port')), - ('asset', - models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='protocols', to='assets.asset', - verbose_name='Asset')), - ], - ), - migrations.RunPython(migrate_asset_protocols), - ] diff --git a/apps/assets/migrations/0100_auto_20220711_1413.py b/apps/assets/migrations/0100_auto_20220711_1413.py deleted file mode 100644 index dd7e34394..000000000 --- a/apps/assets/migrations/0100_auto_20220711_1413.py +++ /dev/null @@ -1,270 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-11 06:13 - -import time -import math -from django.utils import timezone -from itertools import groupby -from django.db import migrations - - -def migrate_asset_accounts(apps, schema_editor): - auth_book_model = apps.get_model('assets', 'AuthBook') - account_model = apps.get_model('accounts', 'Account') - account_history_model = apps.get_model('accounts', 'HistoricalAccount') - - count = 0 - bulk_size = 1000 - print("\n\tStart migrate asset accounts") - while True: - start = time.time() - auth_books = auth_book_model.objects \ - .prefetch_related('systemuser') \ - .all()[count:count + bulk_size] - if not auth_books: - break - - count += len(auth_books) - # auth book 和 account 相同的属性 - same_attrs = [ - 'username', 'comment', 'date_created', 'date_updated', - 'created_by', 'asset_id', 'org_id', - ] - # 认证的属性,可能是 auth_book 的,可能是 system_user 的 - auth_attrs = ['password', 'private_key', 'token'] - all_attrs = same_attrs + auth_attrs - - accounts = [] - for auth_book in auth_books: - account_values = {'version': 1} - - system_user = auth_book.systemuser - if system_user: - # 更新一次系统用户的认证属性 - account_values.update({attr: getattr(system_user, attr, '') for attr in all_attrs}) - account_values['privileged'] = system_user.type == 'admin' \ - or system_user.username in ['root', 'Administrator'] - if system_user.su_enabled and system_user.su_from: - created_by = f'{str(system_user.id)}::{str(system_user.su_from.username)}' - else: - created_by = str(system_user.id) - account_values['created_by'] = created_by - - auth_book_auth = {attr: getattr(auth_book, attr, '') for attr in all_attrs if getattr(auth_book, attr, '')} - # 最终优先使用 auth_book 的认证属性 - account_values.update(auth_book_auth) - - auth_infos = [] - username = account_values.get('username') - if not username: - continue - - for attr in auth_attrs: - secret = account_values.pop(attr, None) - if not secret: - continue - - if attr == 'private_key': - secret_type = 'ssh_key' - name = f'{username}(ssh key)' - elif attr == 'token': - secret_type = 'token' - name = f'{username}(token)' - else: - secret_type = attr - name = username - auth_infos.append((name, secret_type, secret)) - - if not auth_infos: - auth_infos.append((username, 'password', '')) - - for name, secret_type, secret in auth_infos: - if not name: - continue - account = account_model(**account_values, name=name, secret=secret, secret_type=secret_type) - accounts.append(account) - - accounts.sort(key=lambda x: (x.name, x.asset_id, x.date_updated)) - grouped_accounts = groupby(accounts, lambda x: (x.name, x.asset_id)) - - accounts_to_add = [] - accounts_to_history = [] - for key, _accounts in grouped_accounts: - _accounts = list(_accounts) - if not _accounts: - continue - _account = _accounts[-1] - accounts_to_add.append(_account) - _account_history = [] - - for ac in _accounts: - if not ac.secret: - continue - if ac.id != _account.id and ac.secret == _account.secret: - continue - history_data = { - 'id': _account.id, - 'secret': ac.secret, - 'secret_type': ac.secret_type, - 'history_date': ac.date_updated, - 'history_type': '~', - 'history_change_reason': 'from account {}'.format(_account.name), - } - _account_history.append(account_history_model(**history_data)) - _account.version = len(_account_history) - accounts_to_history.extend(_account_history) - - account_model.objects.bulk_create(accounts_to_add, ignore_conflicts=True) - account_history_model.objects.bulk_create(accounts_to_history, ignore_conflicts=True) - print("\t - Create asset accounts: {}-{} using: {:.2f}s".format( - count - len(auth_books), count, time.time() - start - )) - print("\t - accounts: {}".format(len(accounts_to_add))) - print("\t - histories: {}".format(len(accounts_to_history))) - - -def update_asset_accounts_su_from(apps, schema_editor): - # Update accounts su_from - print("\n\tStart update asset accounts su_from field") - account_model = apps.get_model('accounts', 'Account') - platform_model = apps.get_model('assets', 'Platform') - asset_model = apps.get_model('assets', 'Asset') - platform_ids = list(platform_model.objects.filter(su_enabled=True).values_list('id', flat=True)) - - count = 0 - step_size = 1000 - count_account = 0 - while True: - start = time.time() - asset_ids = asset_model.objects \ - .filter(platform_id__in=platform_ids) \ - .values_list('id', flat=True)[count:count + step_size] - asset_ids = list(asset_ids) - if not asset_ids: - break - count += len(asset_ids) - - accounts = list(account_model.objects.filter(asset_id__in=asset_ids)) - - # {asset_id_account_username: account.id}} - asset_accounts_mapper = {} - for a in accounts: - try: - k = f'{a.asset_id}_{a.username}' - asset_accounts_mapper[k] = str(a.id) - except Exception as e: - pass - - update_accounts = [] - for a in accounts: - try: - if not a.created_by: - continue - created_by_list = a.created_by.split('::') - if len(created_by_list) != 2: - continue - su_from_username = created_by_list[1] - if not su_from_username: - continue - k = f'{a.asset_id}_{su_from_username}' - su_from_id = asset_accounts_mapper.get(k) - if not su_from_id: - continue - a.su_from_id = su_from_id - update_accounts.append(a) - except Exception as e: - pass - - count_account += len(update_accounts) - - log_msg = "\t - [{}]: Update accounts su_from: {}-{} {:.2f}s" - try: - account_model.objects.bulk_update(update_accounts, ['su_from_id']) - except Exception as e: - status = 'Failed' - else: - status = 'Success' - print(log_msg.format(status, count_account - len(update_accounts), count_account, time.time() - start)) - - -def migrate_db_accounts(apps, schema_editor): - app_perm_model = apps.get_model('perms', 'ApplicationPermission') - account_model = apps.get_model('accounts', 'Account') - perms = app_perm_model.objects.filter(category__in=['db', 'cloud']) - - same_attrs = [ - 'username', 'comment', 'date_created', 'date_updated', - 'created_by', 'org_id', - ] - auth_attrs = ['password', 'private_key', 'token'] - all_attrs = same_attrs + auth_attrs - - print("\n\tStart migrate app accounts") - - index = 0 - total = perms.count() - - for perm in perms: - index += 1 - start = time.time() - - apps = perm.applications.all() - system_users = perm.system_users.all() - accounts = [] - for s in system_users: - values = {'version': 1} - values.update({attr: getattr(s, attr, '') for attr in all_attrs}) - values['created_by'] = str(s.id) - - auth_infos = [] - username = values['username'] - for attr in auth_attrs: - secret = values.pop(attr, None) - if not secret: - continue - - if attr == 'private_key': - secret_type = 'ssh_key' - name = f'{username}(ssh key)' - elif attr == 'token': - secret_type = 'token' - name = f'{username}(token)' - else: - secret_type = attr - name = username or f'{username}(password)' - auth_infos.append((name, secret_type, secret)) - - if not auth_infos: - name = username or f'{username}(password)' - auth_infos.append((name, 'password', '')) - - for name, secret_type, secret in auth_infos: - values['name'] = name - values['secret_type'] = secret_type - values['secret'] = secret - - if not name: - continue - - for app in apps: - values['asset_id'] = str(app.id) - account = account_model(**values) - accounts.append(account) - - account_model.objects.bulk_create(accounts, ignore_conflicts=True) - - print("\t - Progress ({}/{}), Create app accounts: {} using: {:.2f}s".format( - index, total, len(accounts), time.time() - start - )) - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0001_initial'), - ('assets', '0099_auto_20220711_1409'), - ] - - operations = [ - migrations.RunPython(migrate_asset_accounts), - migrations.RunPython(update_asset_accounts_su_from), - migrations.RunPython(migrate_db_accounts), - ] diff --git a/apps/assets/migrations/0101_auto_20220811_1511.py b/apps/assets/migrations/0101_auto_20220811_1511.py deleted file mode 100644 index 0287a8414..000000000 --- a/apps/assets/migrations/0101_auto_20220811_1511.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-11 07:11 -import django.db.models -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0100_auto_20220711_1413'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='platform', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assets', - to='assets.platform', verbose_name='Platform'), - ), - migrations.RemoveField( - model_name='asset', - name='admin_user', - ), - migrations.RemoveField( - model_name='asset', - name='port', - ), - migrations.RemoveField( - model_name='asset', - name='protocol', - ), - migrations.RemoveField( - model_name='asset', - name='_protocols', - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.RemoveField( - model_name='asset', - name='number', - ), - migrations.RemoveField( - model_name='asset', - name='public_ip', - ), - ] diff --git a/apps/assets/migrations/0102_auto_20220816_1022.py b/apps/assets/migrations/0102_auto_20220816_1022.py deleted file mode 100644 index 922fb23e9..000000000 --- a/apps/assets/migrations/0102_auto_20220816_1022.py +++ /dev/null @@ -1,67 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 02:22 -import time -from django.db import migrations, models -from django.db.models import Count - - -def migrate_command_filter_to_assets(apps, schema_editor): - command_filter_model = apps.get_model('assets', 'CommandFilter') - - count = 0 - bulk_size = 1000 - print("\n\tStart migrate command filters to assets") - while True: - start = time.time() - command_filters = command_filter_model.objects.all() \ - .prefetch_related('system_users')[count:count + bulk_size] - if not command_filters: - break - count += len(command_filters) - updated = [] - for command_filter in command_filters: - command_filter.accounts = [s.username for s in command_filter.system_users.all()] - updated.append(command_filter) - command_filter_model.objects.bulk_update(updated, ['accounts']) - - print("\tCreate assets: {}-{} using: {:.2f}s".format( - count - len(command_filters), count, time.time() - start - )) - - -def migrate_command_filter_apps(apps, schema_editor): - command_filter_model = apps.get_model('assets', 'CommandFilter') - command_filters = command_filter_model.objects \ - .annotate(app_count=Count('applications')) \ - .filter(app_count__gt=0) - - for command_filter in command_filters: - app_ids = command_filter.applications.all().values_list('id', flat=True) - - try: - command_filter.assets.add(*app_ids) - except: - print("Migrate command filter apps failed: {}, skip".format(command_filter.id)) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0101_auto_20220811_1511'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilter', - name='accounts', - field=models.JSONField(default=list, verbose_name='Accounts'), - ), - migrations.RunPython(migrate_command_filter_to_assets), - migrations.RemoveField( - model_name='commandfilter', - name='system_users', - ), - migrations.RunPython(migrate_command_filter_apps), - migrations.RemoveField( - model_name='commandfilter', - name='applications', - ), - ] diff --git a/apps/assets/migrations/0103_auto_20220902_1021.py b/apps/assets/migrations/0103_auto_20220902_1021.py deleted file mode 100644 index dfc731736..000000000 --- a/apps/assets/migrations/0103_auto_20220902_1021.py +++ /dev/null @@ -1,103 +0,0 @@ -# Generated by Django 3.2.13 on 2022-09-29 11:03 - -from django.db import migrations - -from assets.const.host import GATEWAY_NAME - - -def _create_account_obj(secret, secret_type, gateway, asset, account_model): - return account_model( - asset=asset, - secret=secret, - org_id=gateway.org_id, - secret_type=secret_type, - username=gateway.username, - name=f'{gateway.name}-{secret_type}-{GATEWAY_NAME.lower()}', - ) - - -def migrate_gateway_to_asset(apps, schema_editor): - db_alias = schema_editor.connection.alias - node_model = apps.get_model('assets', 'Node') - org_model = apps.get_model('orgs', 'Organization') - gateway_model = apps.get_model('assets', 'Gateway') - platform_model = apps.get_model('assets', 'Platform') - gateway_platform = platform_model.objects.using(db_alias).get(name=GATEWAY_NAME) - - print('>>> migrate gateway to asset') - asset_dict = {} - host_model = apps.get_model('assets', 'Host') - asset_model = apps.get_model('assets', 'Asset') - protocol_model = apps.get_model('assets', 'Protocol') - gateways = gateway_model.objects.all() - - org_ids = gateways.order_by('org_id').values_list('org_id', flat=True).distinct() - node_dict = {} - for org_id in org_ids: - org = org_model.objects.using(db_alias).filter(id=org_id).first() - node = node_model.objects.using(db_alias).filter( - org_id=org_id, value=org.name, full_value=f'/{org.name}' - ).first() - node_dict[org_id] = node - - for gateway in gateways: - comment = gateway.comment if gateway.comment else '' - data = { - 'comment': comment, - 'name': f'{gateway.name}-{GATEWAY_NAME.lower()}', - 'address': gateway.ip, - 'domain': gateway.domain, - 'org_id': gateway.org_id, - 'is_active': gateway.is_active, - 'platform': gateway_platform, - } - asset = asset_model.objects.using(db_alias).create(**data) - node = node_dict.get(str(gateway.org_id)) - asset.nodes.set([node]) - asset_dict[gateway.id] = asset - protocol_model.objects.using(db_alias).create(name='ssh', port=gateway.port, asset=asset) - hosts = [host_model(asset_ptr=asset) for asset in asset_dict.values()] - host_model.objects.using(db_alias).bulk_create(hosts, ignore_conflicts=True) - - print('>>> migrate gateway to account') - accounts = [] - account_model = apps.get_model('accounts', 'Account') - for gateway in gateways: - password = gateway.password - private_key = gateway.private_key - asset = asset_dict[gateway.id] - if password: - accounts.append(_create_account_obj( - password, 'password', gateway, asset, account_model - )) - - if private_key: - accounts.append(_create_account_obj( - private_key, 'ssh_key', gateway, asset, account_model - )) - account_model.objects.using(db_alias).bulk_create(accounts) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0102_auto_20220816_1022'), - ] - - operations = [ - migrations.RunPython(migrate_gateway_to_asset), - migrations.DeleteModel( - name='Gateway', - ), - migrations.CreateModel( - name='Gateway', - fields=[ - ], - options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], - 'verbose_name': 'Gateway' - }, - bases=('assets.host',), - ), - ] diff --git a/apps/assets/migrations/0104_auto_20220817_1544.py b/apps/assets/migrations/0104_auto_20220817_1544.py deleted file mode 100644 index 972c34e09..000000000 --- a/apps/assets/migrations/0104_auto_20220817_1544.py +++ /dev/null @@ -1,61 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 07:44 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0103_auto_20220902_1021'), - ] - - operations = [ - migrations.RemoveField( - model_name='historicalauthbook', - name='asset', - ), - migrations.RemoveField( - model_name='historicalauthbook', - name='history_user', - ), - migrations.RemoveField( - model_name='historicalauthbook', - name='systemuser', - ), - migrations.RemoveField( - model_name='systemuser', - name='assets', - ), - migrations.RemoveField( - model_name='systemuser', - name='groups', - ), - migrations.RemoveField( - model_name='systemuser', - name='nodes', - ), - migrations.RemoveField( - model_name='systemuser', - name='users', - ), - migrations.AlterUniqueTogether( - name='authbook', - unique_together=None, - ), - migrations.RemoveField( - model_name='authbook', - name='asset', - ), - migrations.RemoveField( - model_name='authbook', - name='systemuser', - ), - migrations.DeleteModel( - name='Cluster', - ), - migrations.DeleteModel( - name='HistoricalAuthBook', - ), - migrations.DeleteModel( - name='AuthBook', - ), - ] diff --git a/apps/assets/migrations/0105_auto_20221220_1956.py b/apps/assets/migrations/0105_auto_20221220_1956.py deleted file mode 100644 index 196a33fb8..000000000 --- a/apps/assets/migrations/0105_auto_20221220_1956.py +++ /dev/null @@ -1,127 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0104_auto_20220817_1544'), - ] - - operations = [ - migrations.AddField( - model_name='domain', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='domain', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='domain', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='favoriteasset', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='favoriteasset', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='node', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='node', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='node', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AddField( - model_name='node', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='node', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='label', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='label', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='label', - name='updated_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='platformprotocol', - name='default', - field=models.BooleanField(default=False, verbose_name='Default'), - ), - migrations.AlterField( - model_name='gateway', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='asset', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='asset', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='domain', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='favoriteasset', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='label', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='label', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='label', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='gateway', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - ] diff --git a/apps/assets/migrations/0106_auto_20221228_1838.py b/apps/assets/migrations/0106_auto_20221228_1838.py deleted file mode 100644 index ce7718ccd..000000000 --- a/apps/assets/migrations/0106_auto_20221228_1838.py +++ /dev/null @@ -1,80 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-28 10:38 - -import common.db.fields -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0105_auto_20221220_1956'), - ('tickets', '0025_auto_20221206_1820'), - ] - - operations = [ - migrations.RemoveField( - model_name='accountbackupplanexecution', - name='plan', - ), - migrations.AlterUniqueTogether( - name='commandfilter', - unique_together=None, - ), - migrations.RemoveField( - model_name='commandfilter', - name='assets', - ), - migrations.RemoveField( - model_name='commandfilter', - name='nodes', - ), - migrations.RemoveField( - model_name='commandfilter', - name='user_groups', - ), - migrations.RemoveField( - model_name='commandfilter', - name='users', - ), - migrations.RemoveField( - model_name='commandfilterrule', - name='filter', - ), - migrations.RemoveField( - model_name='commandfilterrule', - name='reviewers', - ), - migrations.RemoveField( - model_name='gathereduser', - name='asset', - ), - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['name'], - 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetaccount', 'Can push account to asset'), ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, - ), - migrations.AlterUniqueTogether( - name='accountbackupplan', - unique_together=None, - ), - migrations.RemoveField( - model_name='accountbackupplan', - name='recipients', - ), - migrations.DeleteModel( - name='AccountBackupPlanExecution', - ), - migrations.DeleteModel( - name='CommandFilter', - ), - migrations.DeleteModel( - name='CommandFilterRule', - ), - migrations.DeleteModel( - name='GatheredUser', - ), - migrations.DeleteModel( - name='AccountBackupPlan', - ), - ] diff --git a/apps/assets/migrations/0107_automation.py b/apps/assets/migrations/0107_automation.py deleted file mode 100644 index 6841cb912..000000000 --- a/apps/assets/migrations/0107_automation.py +++ /dev/null @@ -1,96 +0,0 @@ -# Generated by Django 3.2.16 on 2022-12-30 08:08 - -import common.db.fields -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0106_auto_20221228_1838'), - ] - - operations = [ - migrations.CreateModel( - name='BaseAutomation', - fields=[ - ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic perform')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')), - ('accounts', models.JSONField(default=list, verbose_name='Accounts')), - ('type', models.CharField(max_length=16, verbose_name='Type')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('assets', models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets')), - ('nodes', models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Node')), - ], - options={ - 'verbose_name': 'Automation task', - 'unique_together': {('org_id', 'name', 'type')}, - }, - ), - migrations.CreateModel( - name='AutomationExecution', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), - ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), - ('snapshot', common.db.fields.EncryptJsonDictTextField(blank=True, default=dict, null=True, verbose_name='Automation snapshot')), - ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), - ('automation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task')), - ], - options={ - 'verbose_name': 'Automation task execution', - 'ordering': ('-date_start',), - }, - ), - migrations.CreateModel( - name='AssetBaseAutomation', - fields=[ - ], - options={ - 'verbose_name': 'Asset automation task', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.baseautomation',), - ), - migrations.CreateModel( - name='GatherFactsAutomation', - fields=[ - ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Gather asset facts', - }, - bases=('assets.assetbaseautomation',), - ), - migrations.CreateModel( - name='PingAutomation', - fields=[ - ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Ping asset', - }, - bases=('assets.assetbaseautomation',), - ), - migrations.AlterField( - model_name='automationexecution', - name='automation', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'), - ), - ] diff --git a/apps/assets/migrations/0108_alter_platform_charset.py b/apps/assets/migrations/0108_alter_platform_charset.py deleted file mode 100644 index d413068f1..000000000 --- a/apps/assets/migrations/0108_alter_platform_charset.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-07 04:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0107_automation'), - ] - - operations = [ - migrations.AlterField( - model_name='platform', - name='charset', - field=models.CharField(choices=[('utf-8', 'UTF-8'), ('gbk', 'GBK')], default='utf-8', max_length=8, verbose_name='Charset'), - ), - migrations.AddField( - model_name='platform', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='platform', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AddField( - model_name='platform', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='platform', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='platform', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - ] diff --git a/apps/assets/migrations/0109_alter_asset_options.py b/apps/assets/migrations/0109_alter_asset_options.py deleted file mode 100644 index 9140eff74..000000000 --- a/apps/assets/migrations/0109_alter_asset_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-14 07:28 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0108_alter_platform_charset'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': [], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('match_asset', 'Can match asset'), ('change_assetnodes', 'Can change asset nodes')], 'verbose_name': 'Asset'}, - ), - ] diff --git a/apps/assets/migrations/0110_auto_20230315_1741.py b/apps/assets/migrations/0110_auto_20230315_1741.py deleted file mode 100644 index 2c0468d87..000000000 --- a/apps/assets/migrations/0110_auto_20230315_1741.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-03-15 09:41 - -from django.db import migrations - - -def set_windows_platform_non_console(apps, schema_editor): - Platform = apps.get_model('assets', 'Platform') - names = ['Windows', 'Windows-RDP', 'Windows-TLS', 'RemoteAppHost'] - windows = Platform.objects.filter(name__in=names) - if not windows: - return - - for p in windows: - rdp = p.protocols.filter(name='rdp').first() - if not rdp: - continue - rdp.setting['console'] = False - rdp.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0109_alter_asset_options'), - ] - - operations = [ - migrations.RunPython(set_windows_platform_non_console) - ] diff --git a/apps/assets/migrations/0111_auto_20230321_1633.py b/apps/assets/migrations/0111_auto_20230321_1633.py deleted file mode 100644 index e9f19ea0e..000000000 --- a/apps/assets/migrations/0111_auto_20230321_1633.py +++ /dev/null @@ -1,100 +0,0 @@ -# Generated by Django 3.2.17 on 2023-03-21 08:33 - -from django.db import migrations, models - - -def migrate_platform_charset(apps, schema_editor): - platform_model = apps.get_model('assets', 'Platform') - platform_model.objects.filter(charset='utf8').update(charset='utf-8') - - -def migrate_platform_protocol_primary(apps, schema_editor): - platform_model = apps.get_model('assets', 'Platform') - platforms = platform_model.objects.all() - - for platform in platforms: - p = platform.protocols.filter(primary=True).first() - if p: - continue - p = platform.protocols.first() - if not p: - continue - p.primary = True - p.save() - - -def migrate_winrm_for_win(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - windows_name = ['Windows', 'Windows-TLS', 'Windows-RDP'] - windows = platform_cls.objects.filter(name__in=windows_name) - for platform in windows: - if platform.protocols.filter(name='winrm').exists(): - continue - data = { - 'name': 'winrm', - 'port': 5985, - 'primary': False, - 'public': False, - 'required': False, - 'default': False, - 'setting': {"use_ssl": False} - } - platform.protocols.create(**data) - - -def migrate_device_platform_automation(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - names = ['General', 'Cisco', 'H3C', 'Huawei'] - platforms = platform_cls.objects.filter(name__in=names, category='device') - - for platform in platforms: - automation = getattr(platform, 'automation', None) - if not automation: - continue - automation.ansible_config = { - "ansible_connection": "local", - "first_connect_delay": 0.5, - } - automation.ansible_enabled = True - automation.change_secret_enabled = True - automation.change_secret_method = "change_secret_by_ssh" - automation.ping_enabled = True - automation.ping_method = "ping_by_ssh" - automation.verify_account_enabled = True - automation.verify_account_method = "verify_account_by_ssh" - automation.save() - - -def migrate_web_login_button_error(apps, *args): - protocol_cls = apps.get_model('assets', 'PlatformProtocol') - protocols = protocol_cls.objects.filter(name='http') - - for protocol in protocols: - submit_selector = protocol.setting.get('submit_selector', '') - submit_selector = submit_selector.replace('id=longin_button', 'id=login_button') - protocol.setting['submit_selector'] = submit_selector - protocol.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0110_auto_20230315_1741'), - ] - - operations = [ - migrations.AddField( - model_name='platformprotocol', - name='primary', - field=models.BooleanField(default=False, verbose_name='Primary'), - ), - migrations.AddField( - model_name='platformprotocol', - name='public', - field=models.BooleanField(default=True, verbose_name='Public'), - ), - migrations.RunPython(migrate_platform_charset), - migrations.RunPython(migrate_platform_protocol_primary), - migrations.RunPython(migrate_winrm_for_win), - migrations.RunPython(migrate_device_platform_automation), - migrations.RunPython(migrate_web_login_button_error), - ] diff --git a/apps/assets/migrations/0112_auto_20230404_1631.py b/apps/assets/migrations/0112_auto_20230404_1631.py deleted file mode 100644 index 72285123a..000000000 --- a/apps/assets/migrations/0112_auto_20230404_1631.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-04 08:31 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0111_auto_20230321_1633'), - ] - - operations = [ - migrations.CreateModel( - name='Custom', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'verbose_name': 'Custom asset', - }, - bases=('assets.asset',), - ), - migrations.AddField( - model_name='platform', - name='custom_fields', - field=models.JSONField(default=list, null=True, verbose_name='Custom fields'), - ), - migrations.AddField( - model_name='asset', - name='custom_info', - field=models.JSONField(default=dict, verbose_name='Custom info'), - ), - migrations.AddField( - model_name='asset', - name='gathered_info', - field=models.JSONField(blank=True, default=dict, verbose_name='Gathered info'), - ), - migrations.RemoveField( - model_name='asset', - name='info', - ), - ] diff --git a/apps/assets/migrations/0113_auto_20230411_1917.py b/apps/assets/migrations/0113_auto_20230411_1917.py deleted file mode 100644 index ca41a30ab..000000000 --- a/apps/assets/migrations/0113_auto_20230411_1917.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-11 11:17 - -from django.db import migrations - - -def migrate_device_platform_su_method(apps, schema_editor): - platform_model = apps.get_model('assets', 'Platform') - device_map = { - 'Huawei': 'super', - 'Cisco': 'enable', - 'H3C': 'super_level', - } - platforms = platform_model.objects.filter(name__in=device_map.keys()) - print() - for platform in platforms: - print("Migrate platform su method: {}".format(platform.name)) - if platform.name not in device_map: - continue - platform.su_method = device_map[platform.name] - platform.su_enabled = True - platform.save(update_fields=['su_method', 'su_enabled']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0112_auto_20230404_1631'), - ] - - operations = [ - migrations.RunPython(migrate_device_platform_su_method) - ] diff --git a/apps/assets/migrations/0114_baseautomation_params.py b/apps/assets/migrations/0114_baseautomation_params.py deleted file mode 100644 index b48f5b302..000000000 --- a/apps/assets/migrations/0114_baseautomation_params.py +++ /dev/null @@ -1,68 +0,0 @@ -# Generated by Django 3.2.16 on 2023-04-13 10:18 - -from django.db import migrations, models - - -def migrate_automation_push_account_params(apps, schema_editor): - platform_automation_model = apps.get_model('assets', 'PlatformAutomation') - methods_id_data_map = { - 'push_account_aix': {'sudo': '/bin/whoami', 'shell': '/bin/bash', 'home': '', 'groups': ''}, - 'push_account_posix': {'sudo': '/bin/whoami', 'shell': '/bin/bash', 'home': '', 'groups': ''}, - 'push_account_local_windows': {'groups': 'Users,Remote Desktop Users'}, - } - automation_objs = [] - for automation in platform_automation_model.objects.all(): - push_account_method = automation.push_account_method - if not push_account_method: - continue - value = methods_id_data_map.get(push_account_method) - if value is None: - continue - automation.push_account_params = value - automation_objs.append(automation) - platform_automation_model.objects.bulk_update(automation_objs, ['push_account_params']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0113_auto_20230411_1917'), - ] - - operations = [ - migrations.AddField( - model_name='baseautomation', - name='params', - field=models.JSONField(default=dict, verbose_name='Params'), - ), - migrations.AddField( - model_name='platformautomation', - name='change_secret_params', - field=models.JSONField(default=dict, verbose_name='Change secret params'), - ), - migrations.AddField( - model_name='platformautomation', - name='gather_accounts_params', - field=models.JSONField(default=dict, verbose_name='Gather facts params'), - ), - migrations.AddField( - model_name='platformautomation', - name='gather_facts_params', - field=models.JSONField(default=dict, verbose_name='Gather facts params'), - ), - migrations.AddField( - model_name='platformautomation', - name='ping_params', - field=models.JSONField(default=dict, verbose_name='Ping params'), - ), - migrations.AddField( - model_name='platformautomation', - name='push_account_params', - field=models.JSONField(default=dict, verbose_name='Push account params'), - ), - migrations.AddField( - model_name='platformautomation', - name='verify_account_params', - field=models.JSONField(default=dict, verbose_name='Verify account params'), - ), - migrations.RunPython(migrate_automation_push_account_params), - ] diff --git a/apps/assets/migrations/0115_auto_20230417_1425.py b/apps/assets/migrations/0115_auto_20230417_1425.py deleted file mode 100644 index 34cd7ef2c..000000000 --- a/apps/assets/migrations/0115_auto_20230417_1425.py +++ /dev/null @@ -1,49 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-17 06:32 - -from django.db import migrations, models - - -def migrate_platform_automation_id(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - for platform in platform_model.objects.all(): - if platform.automation: - platform._automation_id = platform.automation.id - platform.save(update_fields=['_automation_id']) - - -def migrate_automation_platform(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - automation_model = apps.get_model('assets', 'PlatformAutomation') - platforms = platform_model.objects.all() - for platform in platforms: - if not platform._automation_id: - continue - automation = automation_model.objects.filter(id=platform._automation_id).first() - if not automation: - continue - automation.platform = platform - automation.save(update_fields=['platform']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0114_baseautomation_params'), - ] - - operations = [ - migrations.AddField( - model_name='platform', - name='_automation_id', - field=models.UUIDField(editable=False, null=True), - ), - migrations.RunPython(migrate_platform_automation_id), - migrations.RemoveField(model_name='platform', name='automation'), - migrations.AddField( - model_name='platformautomation', - name='platform', - field=models.OneToOneField(null=True, on_delete=models.deletion.CASCADE, - related_name='automation', to='assets.platform'), - ), - migrations.RunPython(migrate_automation_platform), - migrations.RemoveField(model_name='platform', name='_automation_id'), - ] diff --git a/apps/assets/migrations/0116_auto_20230418_1726.py b/apps/assets/migrations/0116_auto_20230418_1726.py deleted file mode 100644 index e15a5cdc0..000000000 --- a/apps/assets/migrations/0116_auto_20230418_1726.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-18 09:26 - -from django.db import migrations - - -def update_remote_app_platform(apps, schema_editor): - platform_cls = apps.get_model('assets', 'Platform') - remote_app_host = platform_cls.objects.filter(name='RemoteAppHost').first() - if not remote_app_host: - return - - protocols = remote_app_host.protocols.all() - for protocol in protocols: - if protocol.name == 'rdp': - protocol.primary = True - protocol.save() - elif protocol.name == 'ssh': - protocol.required = True - protocol.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0115_auto_20230417_1425'), - ] - - operations = [ - migrations.RunPython(update_remote_app_platform) - ] diff --git a/apps/assets/migrations/0117_alter_baseautomation_params.py b/apps/assets/migrations/0117_alter_baseautomation_params.py deleted file mode 100644 index 1fc93bdd3..000000000 --- a/apps/assets/migrations/0117_alter_baseautomation_params.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-06 06:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0116_auto_20230418_1726'), - ] - - operations = [ - migrations.AlterField( - model_name='baseautomation', - name='params', - field=models.JSONField(default=dict, verbose_name='Parameters'), - ), - ] diff --git a/apps/assets/migrations/0118_auto_20230524_1647.py b/apps/assets/migrations/0118_auto_20230524_1647.py deleted file mode 100644 index cfe8c9f99..000000000 --- a/apps/assets/migrations/0118_auto_20230524_1647.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-24 08:45 - -from django.db import migrations - - -def migrate_remote_applet_host_support_winrm(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - protocol_cls = apps.get_model('assets', 'PlatformProtocol') - applet_host_platform = platform_cls.objects.filter(name='RemoteAppHost').first() - if not applet_host_platform: - return - - protocols = applet_host_platform.protocols.all() - if not protocols.filter(name='winrm').exists(): - protocol = protocol_cls(name='winrm', port=5985, public=False, platform=applet_host_platform) - protocol.save() - applet_host_platform.protocols.add(protocol) - - ssh_protocol = protocols.filter(name='ssh').first() - if ssh_protocol: - ssh_protocol.required = False - ssh_protocol.default = True - ssh_protocol.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0117_alter_baseautomation_params'), - ] - - operations = [ - migrations.RunPython(migrate_remote_applet_host_support_winrm) - ] diff --git a/apps/assets/migrations/0119_assets_add_default_node.py b/apps/assets/migrations/0119_assets_add_default_node.py deleted file mode 100644 index a281196f2..000000000 --- a/apps/assets/migrations/0119_assets_add_default_node.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-05 06:28 - -from django.db import migrations - - -# 历史问题一些资产没有关联到节点,这里将这些资产关联到默认节点 -def migrate_asset_add_default_node(apps, *args): - node_model = apps.get_model('assets', 'Node') - asset_model = apps.get_model('assets', 'Asset') - m2m_model = asset_model.nodes.through - assets = asset_model.objects.filter(nodes__isnull=True).only('id', 'org_id') - org_assets_map = {} - for asset in assets: - org_assets_map.setdefault(str(asset.org_id), []).append(str(asset.id)) - - if not org_assets_map: - return - - m2m_objs = [] - for org_id, asset_ids in org_assets_map.items(): - default_node = node_model.objects.filter(parent_key='', org_id=org_id).first() - if not default_node: - continue - m2m_objs.extend( - [ - m2m_model(node=default_node, asset_id=asset_id) - for asset_id in asset_ids - ] - ) - if not m2m_objs: - return - - m2m_model.objects.bulk_create(m2m_objs) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0118_auto_20230524_1647'), - ] - - operations = [ - migrations.RunPython(migrate_asset_add_default_node), - ] diff --git a/apps/assets/migrations/0120_auto_20230630_1613.py b/apps/assets/migrations/0120_auto_20230630_1613.py deleted file mode 100644 index a5205804b..000000000 --- a/apps/assets/migrations/0120_auto_20230630_1613.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-30 08:13 - -import django.db.models.deletion -from django.db import migrations, models - - -def add_chatgpt_platform(apps, schema_editor): - platform_cls = apps.get_model('assets', 'Platform') - automation_cls = apps.get_model('assets', 'PlatformAutomation') - platform = platform_cls.objects.create( - name='ChatGPT', internal=True, category='gpt', type='chatgpt', - domain_enabled=False, su_enabled=False, comment='ChatGPT', - created_by='System', updated_by='System', - ) - platform.protocols.create(name='chatgpt', port=443, primary=True, setting={'api_mode': 'gpt-3.5-turbo'}) - automation_cls.objects.create(ansible_enabled=False, platform=platform) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0119_assets_add_default_node'), - ] - - operations = [ - migrations.CreateModel( - name='GPT', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ('proxy', models.CharField(blank=True, default='', max_length=128, verbose_name='Proxy')), - ], - options={ - 'verbose_name': 'Web', - }, - bases=('assets.asset',), - ), - migrations.RunPython(add_chatgpt_platform) - ] diff --git a/apps/assets/migrations/0121_auto_20230725_1458.py b/apps/assets/migrations/0121_auto_20230725_1458.py deleted file mode 100644 index c5686d950..000000000 --- a/apps/assets/migrations/0121_auto_20230725_1458.py +++ /dev/null @@ -1,100 +0,0 @@ -# Generated by Django 4.1.10 on 2023-07-25 06:58 - -from django.db import migrations -import json - - -def migrate_platforms_sftp_protocol(apps, schema_editor): - platform_protocol_cls = apps.get_model('assets', 'PlatformProtocol') - platform_cls = apps.get_model('assets', 'Platform') - ssh_protocols = platform_protocol_cls.objects \ - .filter(name='ssh', setting__sftp_enabled=True) \ - .exclude(name__in=('Gateway', 'RemoteAppHost')) \ - .filter(platform__type='linux') - platforms_has_sftp = platform_cls.objects.filter(protocols__name='sftp') - - new_protocols = [] - print("\nPlatform add sftp protocol: ") - for protocol in ssh_protocols: - protocol_setting = protocol.setting or {} - if protocol.platform in platforms_has_sftp: - continue - - kwargs = { - 'name': 'sftp', - 'port': protocol.port, - 'primary': False, - 'required': False, - 'default': True, - 'public': True, - 'setting': { - 'sftp_home': protocol_setting.get('sftp_home', '/tmp'), - }, - 'platform': protocol.platform, - } - new_protocol = platform_protocol_cls(**kwargs) - new_protocols.append(new_protocol) - print(" - {}".format(protocol.platform.name)) - - new_protocols_dict = {(protocol.name, protocol.platform): protocol for protocol in new_protocols} - new_protocols = list(new_protocols_dict.values()) - platform_protocol_cls.objects.bulk_create(new_protocols, ignore_conflicts=True) - - -def migrate_assets_sftp_protocol(apps, schema_editor): - asset_cls = apps.get_model('assets', 'Asset') - platform_cls = apps.get_model('assets', 'Platform') - protocol_cls = apps.get_model('assets', 'Protocol') - sftp_platforms = list(platform_cls.objects.filter(protocols__name='sftp').values_list('id')) - - count = 0 - print("\nAsset add sftp protocol: ") - asset_ids = list(asset_cls.objects\ - .filter(platform__in=sftp_platforms)\ - .exclude(protocols__name='sftp')\ - .distinct()\ - .values_list('id', flat=True)) - while True: - _asset_ids = asset_ids[count:count + 1000] - if not _asset_ids: - break - count += 1000 - - new_protocols = [] - ssh_protocols = protocol_cls.objects.filter(name='ssh', asset_id__in=_asset_ids).distinct() - ssh_protocols_map = {protocol.asset_id: protocol for protocol in ssh_protocols} - for asset_id, protocol in ssh_protocols_map.items(): - new_protocols.append(protocol_cls(name='sftp', port=protocol.port, asset_id=asset_id)) - protocol_cls.objects.bulk_create(new_protocols, ignore_conflicts=True) - print(" - Add {}".format(len(new_protocols))) - - -def migrate_telnet_regex(apps, schema_editor): - setting_cls = apps.get_model('settings', 'Setting') - setting = setting_cls.objects.filter(name='TERMINAL_TELNET_REGEX').first() - if not setting: - print("Not found telnet regex setting, skip") - return - try: - value = json.loads(setting.value) - except Exception: - print("Invalid telnet regex setting, skip") - return - platform_protocol_cls = apps.get_model('assets', 'PlatformProtocol') - telnets = platform_protocol_cls.objects.filter(name='telnet') - if telnets.count() > 0: - telnets.update(setting={'success_prompt': value}) - print("Migrate telnet regex setting success: ", telnets.count()) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0120_auto_20230630_1613'), - ] - - operations = [ - migrations.RunPython(migrate_platforms_sftp_protocol), - migrations.RunPython(migrate_assets_sftp_protocol), - migrations.RunPython(migrate_telnet_regex), - ] diff --git a/apps/assets/migrations/0122_auto_20230803_1553.py b/apps/assets/migrations/0122_auto_20230803_1553.py deleted file mode 100644 index 4f3071153..000000000 --- a/apps/assets/migrations/0122_auto_20230803_1553.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-03 07:53 - -from django.db import migrations - - -def migrate_web_setting_safe_mode(apps, schema_editor): - platform_protocol_cls = apps.get_model('assets', 'PlatformProtocol') - protocols = platform_protocol_cls.objects.filter(name='http') - for protocol in protocols: - setting = protocol.setting or {} - setting['safe_mode'] = False - protocol.setting = setting - protocol.save(update_fields=['setting']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0121_auto_20230725_1458'), - ] - - operations = [ - migrations.RunPython(migrate_web_setting_safe_mode), - ] diff --git a/apps/assets/migrations/0123_device_automation_ansible_enabled.py b/apps/assets/migrations/0123_device_automation_ansible_enabled.py deleted file mode 100644 index 3ef3a4c33..000000000 --- a/apps/assets/migrations/0123_device_automation_ansible_enabled.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-13 10:59 - -from django.db import migrations - - -def migrate_device_automation_ansible_enabled(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - automation_model = apps.get_model('assets', 'PlatformAutomation') - ids = platform_model.objects.filter(category='device').values_list('id', flat=True) - automation_model.objects.filter(platform_id__in=ids).update(ansible_enabled=True) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0122_auto_20230803_1553'), - ] - - operations = [ - migrations.RunPython(migrate_device_automation_ansible_enabled) - ] diff --git a/apps/assets/migrations/0124_auto_20231007_1437.py b/apps/assets/migrations/0124_auto_20231007_1437.py deleted file mode 100644 index 5a004c93d..000000000 --- a/apps/assets/migrations/0124_auto_20231007_1437.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-07 06:37 - -from django.db import migrations - - -def add_db2_platform(apps, schema_editor): - platform_cls = apps.get_model('assets', 'Platform') - automation_cls = apps.get_model('assets', 'PlatformAutomation') - platform, _ = platform_cls.objects.update_or_create( - name='DB2', defaults={ - 'name': 'DB2', 'category': 'database', - 'internal': True, 'type': 'db2', - 'domain_enabled': True, 'su_enabled': False, - 'su_method': None, 'comment': 'DB2', 'created_by': 'System', - 'updated_by': 'System', 'custom_fields': [] - } - ) - platform.protocols.update_or_create(name='db2', defaults={ - 'name': 'db2', 'port': 50000, 'primary': True, 'setting': {} - }) - automation_cls.objects.update_or_create(platform=platform, defaults={'ansible_enabled': False}) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0123_device_automation_ansible_enabled'), - ] - - operations = [ - migrations.RunPython(add_db2_platform) - ] diff --git a/apps/assets/migrations/0125_auto_20231011_1053.py b/apps/assets/migrations/0125_auto_20231011_1053.py deleted file mode 100644 index 11161c909..000000000 --- a/apps/assets/migrations/0125_auto_20231011_1053.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-11 02:53 - -from django.db import migrations - - -def change_windows_ping_method(apps, schema_editor): - platform_automation_cls = apps.get_model('assets', 'PlatformAutomation') - automations = platform_automation_cls.objects.filter(platform__name__in=['Windows', 'Windows2016']) - automations.update(ping_method='ping_by_rdp') - automations.update(verify_account_method='verify_account_by_rdp') - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0124_auto_20231007_1437'), - ] - - operations = [ - migrations.RunPython(change_windows_ping_method) - ] diff --git a/apps/assets/migrations/0126_remove_asset_labels.py b/apps/assets/migrations/0126_remove_asset_labels.py deleted file mode 100644 index 44590dc4c..000000000 --- a/apps/assets/migrations/0126_remove_asset_labels.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-22 07:33 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0125_auto_20231011_1053'), - ('labels', '0002_auto_20231103_1659'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='labels', - ), - ] diff --git a/apps/assets/migrations/0127_automation_remove_account.py b/apps/assets/migrations/0127_automation_remove_account.py deleted file mode 100644 index e0746326f..000000000 --- a/apps/assets/migrations/0127_automation_remove_account.py +++ /dev/null @@ -1,55 +0,0 @@ -# Generated by Django 4.1.10 on 2023-12-05 10:03 -from functools import reduce - -from django.db import migrations, models -from django.db.models import F - - -def migrate_automation_ansible_remove_account(apps, *args): - automation_model = apps.get_model('assets', 'PlatformAutomation') - automation_map = { - ('oracle',): 'remove_account_oracle', - ('windows',): 'remove_account_windows', - ('mongodb',): 'remove_account_mongodb', - ('linux', 'unix'): 'remove_account_posix', - ('sqlserver',): 'remove_account_sqlserver', - ('mysql', 'mariadb'): 'remove_account_mysql', - ('postgresql',): 'remove_account_postgresql', - } - - update_objs = [] - types = list(reduce(lambda x, y: x + y, automation_map.keys())) - qs = automation_model.objects.filter(platform__type__in=types).annotate(tp=F('platform__type')) - for automation in qs: - for types, method in automation_map.items(): - if automation.tp in types: - automation.remove_account_enabled = True - automation.remove_account_method = method - break - update_objs.append(automation) - automation_model.objects.bulk_update(update_objs, ['remove_account_enabled', 'remove_account_method']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0126_remove_asset_labels'), - ] - - operations = [ - migrations.AddField( - model_name='platformautomation', - name='remove_account_enabled', - field=models.BooleanField(default=False, verbose_name='Remove account enabled'), - ), - migrations.AddField( - model_name='platformautomation', - name='remove_account_method', - field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Remove account method'), - ), - migrations.AddField( - model_name='platformautomation', - name='remove_account_params', - field=models.JSONField(default=dict, verbose_name='Remove account params'), - ), - migrations.RunPython(migrate_automation_ansible_remove_account) - ] diff --git a/apps/assets/migrations/0128_auto_20240514_1521.py b/apps/assets/migrations/0128_auto_20240514_1521.py deleted file mode 100644 index cad8628fa..000000000 --- a/apps/assets/migrations/0128_auto_20240514_1521.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-07 06:37 - -from django.db import migrations - - -def add_dameng_platform(apps, schema_editor): - platform_cls = apps.get_model('assets', 'Platform') - automation_cls = apps.get_model('assets', 'PlatformAutomation') - platform, _ = platform_cls.objects.update_or_create( - name='Dameng', defaults={ - 'name': 'Dameng', 'category': 'database', - 'internal': True, 'type': 'dameng', - 'domain_enabled': True, 'su_enabled': False, - 'su_method': None, 'comment': 'Dameng', 'created_by': 'System', - 'updated_by': 'System', 'custom_fields': [] - } - ) - platform.protocols.update_or_create(name='dameng', defaults={ - 'name': 'dameng', 'port': 5236, 'primary': True, 'setting': {} - }) - automation_cls.objects.update_or_create(platform=platform, defaults={'ansible_enabled': False}) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0127_automation_remove_account'), - ] - - operations = [ - migrations.RunPython(add_dameng_platform) - ] diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py index 5eeaf2626..74bb94517 100644 --- a/apps/assets/models/__init__.py +++ b/apps/assets/models/__init__.py @@ -2,13 +2,8 @@ from .base import * from .platform import * from .asset import * from .label import Label -from .group import * from .gateway import * from .domain import * from .node import * from .favorite_asset import * from .automations import * -# 废弃以下 -# from ._authbook import * -# from .cmd_filter import * -from ._user import * diff --git a/apps/assets/models/_user.py b/apps/assets/models/_user.py deleted file mode 100644 index 019147456..000000000 --- a/apps/assets/models/_user.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# - -import logging -import uuid -from common.db import fields - -from django.db import models -from django.utils.translation import gettext_lazy as _ -from django.core.validators import MinValueValidator, MaxValueValidator - -from orgs.mixins.models import OrgModelMixin - - -__all__ = ['SystemUser'] -logger = logging.getLogger(__name__) - - -class OldBaseUser(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) - username = models.CharField(max_length=128, blank=True, verbose_name=_('Username'), db_index=True) - password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) - private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) - public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created")) - date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated")) - created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) - - class Meta: - abstract = True - - -class SystemUser(OrgModelMixin, OldBaseUser): - LOGIN_AUTO = 'auto' - LOGIN_MANUAL = 'manual' - LOGIN_MODE_CHOICES = ( - (LOGIN_AUTO, _('Automatic managed')), - (LOGIN_MANUAL, _('Manually input')) - ) - - class Type(models.TextChoices): - common = 'common', _('Common user') - admin = 'admin', _('Admin user') - - token = models.TextField(default='', verbose_name=_('Token')) - username_same_with_user = models.BooleanField(default=False, verbose_name=_("Username same with user")) - type = models.CharField(max_length=16, choices=Type.choices, default=Type.common, verbose_name=_('Type')) - priority = models.IntegerField(default=81, verbose_name=_("Priority"), help_text=_("1-100, the lower the value will be match first"), validators=[MinValueValidator(1), MaxValueValidator(100)]) - protocol = models.CharField(max_length=16, default='ssh', verbose_name=_('Protocol')) - auto_push = models.BooleanField(default=True, verbose_name=_('Auto push')) - sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo')) - shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) - login_mode = models.CharField(choices=LOGIN_MODE_CHOICES, default=LOGIN_AUTO, max_length=10, verbose_name=_('Login mode')) - sftp_root = models.CharField(default='tmp', max_length=128, verbose_name=_("SFTP Root")) - home = models.CharField(max_length=4096, default='', verbose_name=_('Home'), blank=True) - system_groups = models.CharField(default='', max_length=4096, verbose_name=_('System groups'), blank=True) - ad_domain = models.CharField(default='', max_length=256) - # linux su 命令 (switch user) - su_enabled = models.BooleanField(default=False, verbose_name=_('User switch')) - su_from = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='su_to', null=True, verbose_name=_("Switch from")) - privileged = None - - class Meta: - ordering = ['name'] - unique_together = [('name', 'org_id')] - verbose_name = _("System user") - permissions = [ - ('match_systemuser', _('Can match system user')), - ] - - -# Deprecated: 准备废弃 -class AdminUser(OrgModelMixin, OldBaseUser): - """ - A privileged user that ansible can use it to push system user and so on - """ - BECOME_METHOD_CHOICES = ( - ('sudo', 'sudo'), - ('su', 'su'), - ) - become = models.BooleanField(default=True) - become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4) - become_user = models.CharField(default='root', max_length=64) - _become_pass = models.CharField(default='', blank=True, max_length=128) - - def __str__(self): - return self.name - - class Meta: - ordering = ['name'] - unique_together = [('name', 'org_id')] - verbose_name = _("Admin user") \ No newline at end of file diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index 7d3fb5fd2..9676c3db0 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -160,10 +160,9 @@ class Asset(NodesRelationMixin, LabeledMixin, AbsConnectivity, JSONFilterMixin, address = models.CharField(max_length=767, verbose_name=_('Address'), db_index=True) platform = models.ForeignKey(Platform, on_delete=models.PROTECT, verbose_name=_("Platform"), related_name='assets') domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', - verbose_name=_("Domain"), on_delete=models.SET_NULL) - nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', - verbose_name=_("Node")) - is_active = models.BooleanField(default=True, verbose_name=_('Is active')) + verbose_name=_("Zone"), on_delete=models.SET_NULL) + nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes")) + is_active = models.BooleanField(default=True, verbose_name=_('Active')) gathered_info = models.JSONField(verbose_name=_('Gathered info'), default=dict, blank=True) # 资产的一些信息,如 硬件信息 custom_info = models.JSONField(verbose_name=_('Custom info'), default=dict) diff --git a/apps/assets/models/cmd_filter.py b/apps/assets/models/cmd_filter.py index 63fd7ca34..5b96a0c92 100644 --- a/apps/assets/models/cmd_filter.py +++ b/apps/assets/models/cmd_filter.py @@ -76,7 +76,7 @@ class CommandFilterRule(OrgModelMixin): default=50, verbose_name=_("Priority"), help_text=_("1-100, the lower the value will be match first"), validators=[MinValueValidator(1), MaxValueValidator(100)] ) - content = models.TextField(verbose_name=_("Content"), help_text=_("One line one command")) + content = models.TextField(verbose_name=_("Content"), help_text=_("One command per line")) ignore_case = models.BooleanField(default=True, verbose_name=_('Ignore case')) action = models.IntegerField(default=ActionChoices.deny, choices=ActionChoices.choices, verbose_name=_("Action")) # 动作: 附加字段 diff --git a/apps/assets/models/domain.py b/apps/assets/models/domain.py index e424a2d46..68cbb63c9 100644 --- a/apps/assets/models/domain.py +++ b/apps/assets/models/domain.py @@ -5,7 +5,7 @@ import random from django.db import models from django.utils.translation import gettext_lazy as _ -from common.utils import get_logger +from common.utils import get_logger, lazyproperty from labels.mixins import LabeledMixin from orgs.mixins.models import JMSOrgBaseModel from .gateway import Gateway @@ -19,7 +19,7 @@ class Domain(LabeledMixin, JMSOrgBaseModel): name = models.CharField(max_length=128, verbose_name=_('Name')) class Meta: - verbose_name = _("Domain") + verbose_name = _("Zone") unique_together = [('org_id', 'name')] ordering = ('name',) @@ -29,6 +29,10 @@ class Domain(LabeledMixin, JMSOrgBaseModel): def select_gateway(self): return self.random_gateway() + @lazyproperty + def assets_amount(self): + return self.assets.count() + def random_gateway(self): gateways = [gw for gw in self.active_gateways if gw.is_connective] diff --git a/apps/assets/models/group.py b/apps/assets/models/group.py deleted file mode 100644 index ad3545a1e..000000000 --- a/apps/assets/models/group.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# - -from __future__ import unicode_literals - -import uuid - -from django.db import models -from django.utils.translation import gettext_lazy as _ - -__all__ = ['AssetGroup'] - - -class AssetGroup(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) - created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) - date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date created')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - - def __str__(self): - return self.name - - class Meta: - ordering = ['name'] - verbose_name = _("Asset group") - - @classmethod - def initial(cls): - asset_group = cls(name=_('Default'), comment=_('Default asset group')) - asset_group.save() diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 7ca29e6bd..5b7d7f95a 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -8,11 +8,10 @@ from collections import defaultdict from django.core.cache import cache from django.db import models, transaction -from django.db.models import Q, Manager +from django.db.models import F, Q, Manager from django.db.transaction import atomic from django.utils.translation import gettext_lazy as _, gettext -from common.db.models import output_as_string from common.utils import get_logger, timeit from common.utils.lock import DistributedLock from orgs.mixins.models import OrgManager, JMSOrgBaseModel @@ -354,9 +353,9 @@ class NodeAllAssetsMappingMixin: t1 = time.time() with tmp_to_org(org_id): node_ids_key = Node.objects.annotate( - char_id=output_as_string('id') + char_id=F('id') ).values_list('char_id', 'key') - + node_ids_key = [(str(node_id), node_key) for node_id, node_key in node_ids_key] node_id_ancestor_keys_mapping = { node_id: cls.get_node_ancestor_keys(node_key, with_self=True) for node_id, node_key in node_ids_key @@ -364,12 +363,13 @@ class NodeAllAssetsMappingMixin: # * 直接取出全部. filter(node__org_id=org_id)(大规模下会更慢) nodes_asset_ids = cls.assets.through.objects.all() \ - .annotate(char_node_id=output_as_string('node_id')) \ - .annotate(char_asset_id=output_as_string('asset_id')) \ + .annotate(char_node_id=F('node_id')) \ + .annotate(char_asset_id=F('asset_id')) \ .values_list('char_node_id', 'char_asset_id') nodeid_assetsid_mapping = defaultdict(set) for node_id, asset_id in nodes_asset_ids: + node_id, asset_id = str(node_id), str(asset_id) nodeid_assetsid_mapping[node_id].add(asset_id) t2 = time.time() diff --git a/apps/assets/models/platform.py b/apps/assets/models/platform.py index 85ec8d535..442579e9f 100644 --- a/apps/assets/models/platform.py +++ b/apps/assets/models/platform.py @@ -101,7 +101,7 @@ class Platform(LabeledMixin, JMSBaseModel): default=CharsetChoices.utf8, choices=CharsetChoices.choices, max_length=8, verbose_name=_("Charset") ) - domain_enabled = models.BooleanField(default=True, verbose_name=_("Domain enabled")) + domain_enabled = models.BooleanField(default=True, verbose_name=_("Gateway enabled")) # 账号有关的 su_enabled = models.BooleanField(default=False, verbose_name=_("Su enabled")) su_method = models.CharField(max_length=32, blank=True, null=True, verbose_name=_("Su method")) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 98f2066ad..9a6f21a11 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -125,7 +125,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer, ResourceLabelsMixin, Writa category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category')) type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type')) protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'), default=()) - accounts = AssetAccountSerializer(many=True, required=False, allow_null=True, write_only=True, label=_('Account')) + accounts = AssetAccountSerializer(many=True, required=False, allow_null=True, write_only=True, label=_('Accounts')) nodes_display = serializers.ListField(read_only=False, required=False, label=_("Node path")) _accounts = None @@ -140,16 +140,16 @@ class AssetSerializer(BulkOrgResourceModelSerializer, ResourceLabelsMixin, Writa ] read_only_fields = [ 'category', 'type', 'connectivity', 'auto_config', - 'date_verified', 'created_by', 'date_created', + 'date_verified', 'created_by', 'date_created', 'date_updated', ] fields = fields_small + fields_fk + fields_m2m + read_only_fields fields_unexport = ['auto_config'] extra_kwargs = { 'auto_config': {'label': _('Auto info')}, - 'name': {'label': _("Name")}, + 'name': {'label': _("Name"), 'initial': 'Asset name'}, 'address': {'label': _('Address')}, 'nodes_display': {'label': _('Node path')}, - 'nodes': {'allow_empty': True}, + 'nodes': {'allow_empty': True, 'label': _("Nodes")}, } def __init__(self, *args, **kwargs): @@ -323,7 +323,9 @@ class AssetSerializer(BulkOrgResourceModelSerializer, ResourceLabelsMixin, Writa template_id = data.get('template', None) if template_id: template = AccountTemplate.objects.get(id=template_id) - if template and template.su_from: + template.push_params = data.pop('push_params', {}) + data['params'] = template.push_params + if template.su_from: su_from_name_username_secret_type_map[template.name] = ( template.su_from.username, template.su_from.secret_type ) diff --git a/apps/assets/serializers/automations/base.py b/apps/assets/serializers/automations/base.py index f720ed077..4622c0674 100644 --- a/apps/assets/serializers/automations/base.py +++ b/apps/assets/serializers/automations/base.py @@ -1,4 +1,4 @@ -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from assets.models import Asset, Node, BaseAutomation, AutomationExecution @@ -31,7 +31,6 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe extra_kwargs = { 'name': {'required': True}, 'type': {'read_only': True}, - 'periodic_display': {'label': _('Periodic perform')}, } diff --git a/apps/assets/serializers/domain.py b/apps/assets/serializers/domain.py index 4224e3983..5e70282f5 100644 --- a/apps/assets/serializers/domain.py +++ b/apps/assets/serializers/domain.py @@ -4,10 +4,10 @@ from django.db.models import Count, Q from django.utils.translation import gettext_lazy as _ from rest_framework import serializers +from assets.models.gateway import Gateway from common.serializers import ResourceLabelsMixin from common.serializers.fields import ObjectRelatedField from orgs.mixins.serializers import BulkOrgResourceModelSerializer -from assets.models.gateway import Gateway from .gateway import GatewayWithAccountSecretSerializer from ..models import Domain @@ -16,18 +16,22 @@ __all__ = ['DomainSerializer', 'DomainWithGatewaySerializer', 'DomainListSeriali class DomainSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer): gateways = ObjectRelatedField( - many=True, required=False, label=_('Gateway'), queryset=Gateway.objects + many=True, required=False, label=_('Gateway'), queryset=Gateway.objects, + help_text=_( + "A gateway is a network proxy for a zone, and when connecting assets within the zone, " + "the connection is routed through the gateway.") ) + assets_amount = serializers.IntegerField(label=_('Assets amount'), read_only=True) class Meta: model = Domain fields_mini = ['id', 'name'] fields_small = fields_mini + ['comment'] - fields_m2m = ['assets', 'gateways'] + fields_m2m = ['assets', 'gateways', 'assets_amount'] read_only_fields = ['date_created'] fields = fields_small + fields_m2m + read_only_fields extra_kwargs = { - 'assets': {'required': False}, + 'assets': {'required': False, 'label': _('Assets')}, } def to_representation(self, instance): @@ -54,13 +58,12 @@ class DomainSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer): @classmethod def setup_eager_loading(cls, queryset): queryset = queryset \ + .annotate(assets_amount=Count('assets')) \ .prefetch_related('labels', 'labels__label') return queryset class DomainListSerializer(DomainSerializer): - assets_amount = serializers.IntegerField(label=_('Assets amount'), read_only=True) - class Meta(DomainSerializer.Meta): fields = list(set(DomainSerializer.Meta.fields + ['assets_amount']) - {'assets'}) diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index 4fb0418c6..3441ac6f4 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -27,21 +27,55 @@ class PlatformAutomationSerializer(serializers.ModelSerializer): "change_secret_enabled", "change_secret_method", "change_secret_params", "verify_account_enabled", "verify_account_method", "verify_account_params", "gather_accounts_enabled", "gather_accounts_method", "gather_accounts_params", + "remove_account_enabled", "remove_account_method", "remove_account_params", ] extra_kwargs = { # 启用资产探测 - "ping_enabled": {"label": _("Ping enabled")}, + "ping_enabled": {"label": _("Ping enabled"), "help_text": _("Enable asset detection")}, "ping_method": {"label": _("Ping method")}, - "gather_facts_enabled": {"label": _("Gather facts enabled")}, - "gather_facts_method": {"label": _("Gather facts method")}, - "verify_account_enabled": {"label": _("Verify account enabled")}, - "verify_account_method": {"label": _("Verify account method")}, - "change_secret_enabled": {"label": _("Change secret enabled")}, - "change_secret_method": {"label": _("Change secret method")}, - "push_account_enabled": {"label": _("Push account enabled")}, - "push_account_method": {"label": _("Push account method")}, - "gather_accounts_enabled": {"label": _("Gather accounts enabled")}, - "gather_accounts_method": {"label": _("Gather accounts method")}, + "gather_facts_enabled": { + "label": _("Gather facts enabled"), + "help_text": _("Enable asset information collection") + }, + "gather_facts_method": { + "label": _("Gather facts method"), + }, + "verify_account_enabled": { + "label": _("Verify account enabled"), + "help_text": _("Enable account verification") + }, + "verify_account_method": { + "label": _("Verify account method"), + }, + "change_secret_enabled": { + "label": _("Change secret enabled"), + "help_text": _("Enable account secret auto change") + }, + "change_secret_method": { + "label": _("Change secret method"), + }, + "push_account_enabled": { + "label": _("Push account enabled"), + "help_text": _("Enable account auto push") + }, + "push_account_method": { + "label": _("Push account method"), + }, + "gather_accounts_enabled": { + "label": _("Gather accounts enabled"), + "help_text": _("Enable account collection") + }, + "gather_accounts_method": { + "label": _("Gather accounts method"), + }, + "remove_account_method": { + "label": _("Remove account method"), + }, + "remove_account_enabled": { + "label": _("Remove accounts enabled"), + "help_text": _("Enable account remove"), + }, + } @@ -158,13 +192,21 @@ class PlatformSerializer(ResourceLabelsMixin, WritableNestedModelSerializer): 'created_by', 'updated_by' ] fields = fields_small + [ - "protocols", "domain_enabled", "su_enabled", - "su_method", "automation", "comment", "custom_fields", - "labels" + "protocols", "domain_enabled", "su_enabled", "su_method", + "automation", "comment", "custom_fields", "labels" ] + read_only_fields extra_kwargs = { - "su_enabled": {"label": _('Su enabled')}, - "domain_enabled": {"label": _('Domain enabled')}, + "su_enabled": { + "label": _('Su enabled'), + "help_text": _( + "Login with account when accessing assets, then automatically switch to another, " + "similar to logging in with a regular account and then switching to root" + ) + }, + "domain_enabled": { + "label": _('Gateway enabled'), + "help_text": _("Assets can be connected using a zone gateway") + }, "domain_default": {"label": _('Default Domain')}, } diff --git a/apps/assets/utils/node.py b/apps/assets/utils/node.py index c0a28713d..acadfde60 100644 --- a/apps/assets/utils/node.py +++ b/apps/assets/utils/node.py @@ -2,7 +2,8 @@ # from collections import defaultdict -from common.db.models import output_as_string +from django.db.models import F + from common.struct import Stack from common.utils import get_logger, dict_get_any, is_uuid, get_object_or_none, timeit from common.utils.http import is_true @@ -128,11 +129,12 @@ class NodeAssetsUtil: nodes = list(Node.objects.all()) nodes_assets = Asset.nodes.through.objects.all() \ - .annotate(aid=output_as_string('asset_id')) \ + .annotate(aid=F('asset_id')) \ .values_list('node__key', 'aid') mapping = defaultdict(set) for key, asset_id in nodes_assets: + asset_id = str(asset_id) mapping[key].add(asset_id) util = cls(nodes, mapping) diff --git a/apps/audits/apps.py b/apps/audits/apps.py index ddaa535a7..1d56d13ad 100644 --- a/apps/audits/apps.py +++ b/apps/audits/apps.py @@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _ class AuditsConfig(AppConfig): name = 'audits' - verbose_name = _('Audits') + verbose_name = _('App Audits') def ready(self): from . import signal_handlers # noqa diff --git a/apps/audits/backends/db.py b/apps/audits/backends/db.py index 3a47036bb..44efdd82f 100644 --- a/apps/audits/backends/db.py +++ b/apps/audits/backends/db.py @@ -6,8 +6,9 @@ from perms.const import ActionChoices class OperateLogStore(object): - # 用不可见字符分割前后数据,节省存储-> diff: {'key': 'before\0after'} - SEP = '\0' + # 使用 Unicode 单元分隔符\u001f,替代旧的分隔符\0 PostgreSQL 数据库不支持\0 + SEP = '\u001f' + OLD_SEP = '\0' def __init__(self, config): self.model = OperateLog @@ -20,6 +21,22 @@ class OperateLogStore(object): def ping(timeout=None): return True + @classmethod + def split_value(cls, value): + """ + Attempt to split the string using the new separator. + If it fails, attempt to split using the old separator. + If both fail, return the original string and an empty string. + + :param value: The string to split + :return: The split parts (before, after) + """ + for sep in (cls.SEP, cls.OLD_SEP): + parts = value.split(sep, 1) + if len(parts) == 2: + return parts[0], parts[1] + return value, '' + @classmethod def convert_before_after_to_diff(cls, before, after): if not isinstance(before, dict): @@ -42,7 +59,7 @@ class OperateLogStore(object): return before, after for k, v in diff.items(): - before_value, after_value = v.split(cls.SEP, 1) + before_value, after_value = cls.split_value(v) before[k], after[k] = before_value, after_value return before, after @@ -59,11 +76,11 @@ class OperateLogStore(object): diff_list = list() handler = cls._get_special_handler(op_log.resource_type) for k, v in op_log.diff.items(): - before, after = v.split(cls.SEP, 1) + before_value, after_value = cls.split_value(v) diff_list.append({ 'field': _(k), - 'before': handler(k, before) if before else _('empty'), - 'after': handler(k, after) if after else _('empty'), + 'before': handler(k, before_value) if before_value else _('empty'), + 'after': handler(k, after_value) if after_value else _('empty'), }) return diff_list diff --git a/apps/audits/migrations/0001_initial.py b/apps/audits/migrations/0001_initial.py index 0545c51d6..749a3a877 100644 --- a/apps/audits/migrations/0001_initial.py +++ b/apps/audits/migrations/0001_initial.py @@ -1,10 +1,12 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-06 04:30 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -from django.db import migrations, models import uuid +import django.utils.timezone +from django.db import migrations, models + +import common.db.encoder + class Migration(migrations.Migration): @@ -14,18 +16,110 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='ActivityLog', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('type', models.CharField(choices=[('O', 'Operate log'), ('S', 'Session log'), ('L', 'Login log'), ('T', 'Task')], default=None, max_length=2, null=True, verbose_name='Activity type')), + ('resource_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Resource')), + ('datetime', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime')), + ('detail', models.TextField(blank=True, default='', verbose_name='Detail')), + ('detail_id', models.CharField(default=None, max_length=36, null=True, verbose_name='Detail ID')), + ], + options={ + 'verbose_name': 'Activity log', + 'ordering': ('-datetime',), + }, + ), migrations.CreateModel( name='FTPLog', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user', models.CharField(max_length=128, verbose_name='User')), + ('remote_addr', models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr')), + ('asset', models.CharField(max_length=1024, verbose_name='Asset')), + ('account', models.CharField(max_length=128, verbose_name='Account')), + ('operate', models.CharField(choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'), ('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download'), ('rename_dir', 'Rename dir')], max_length=16, verbose_name='Operate')), + ('filename', models.CharField(max_length=1024, verbose_name='Filename')), + ('is_success', models.BooleanField(default=True, verbose_name='Success')), + ('date_start', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date start')), + ('has_file', models.BooleanField(default=False, verbose_name='Can Download')), + ('session', models.CharField(default=uuid.uuid4, max_length=36, verbose_name='Session')), + ], + options={ + 'verbose_name': 'File transfer log', + }, + ), + migrations.CreateModel( + name='OperateLog', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user', models.CharField(max_length=128, verbose_name='User')), + ('action', models.CharField(choices=[('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), ('create', 'Create'), ('download', 'Download'), ('connect', 'Connect'), ('login', 'Login'), ('change_password', 'Change password'), ('accept', 'Accept'), ('review', 'Review'), ('notice', 'Notifications'), ('reject', 'Reject'), ('approve', 'Approve'), ('close', 'Close'), ('finished', 'Finished')], max_length=16, verbose_name='Action')), + ('resource_type', models.CharField(max_length=64, verbose_name='Resource Type')), + ('resource', models.CharField(max_length=128, verbose_name='Resource')), + ('resource_id', models.CharField(blank=True, db_index=True, default='', max_length=128, verbose_name='Resource')), + ('remote_addr', models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr')), + ('datetime', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime')), + ('diff', models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True)), + ], + options={ + 'verbose_name': 'Operate log', + 'ordering': ('-datetime',), + }, + ), + migrations.CreateModel( + name='PasswordChangeLog', fields=[ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('user', models.CharField(max_length=128, verbose_name='User')), - ('remote_addr', models.CharField(blank=True, max_length=15, null=True, verbose_name='Remote addr')), - ('asset', models.CharField(max_length=1024, verbose_name='Asset')), - ('system_user', models.CharField(max_length=128, verbose_name='System user')), - ('operate', models.CharField(max_length=16, verbose_name='Operate')), - ('filename', models.CharField(max_length=1024, verbose_name='Filename')), - ('is_success', models.BooleanField(default=True, verbose_name='Success')), - ('date_start', models.DateTimeField(auto_now_add=True)), + ('change_by', models.CharField(max_length=128, verbose_name='Change by')), + ('remote_addr', models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr')), + ('datetime', models.DateTimeField(auto_now=True, verbose_name='Datetime')), ], + options={ + 'verbose_name': 'Password change log', + }, + ), + migrations.CreateModel( + name='UserLoginLog', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('username', models.CharField(max_length=128, verbose_name='Username')), + ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, verbose_name='Login type')), + ('ip', models.GenericIPAddressField(verbose_name='Login IP')), + ('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')), + ('user_agent', models.CharField(blank=True, max_length=254, null=True, verbose_name='User agent')), + ('mfa', models.SmallIntegerField(choices=[(0, 'Disabled'), (1, 'Enabled'), (2, '-')], default=2, verbose_name='MFA')), + ('reason', models.CharField(blank=True, default='', max_length=128, verbose_name='Reason')), + ('status', models.BooleanField(choices=[(1, 'Success'), (0, 'Failed')], default=1, verbose_name='Status')), + ('datetime', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Login Date')), + ('backend', models.CharField(default='', max_length=32, verbose_name='Auth backend')), + ], + options={ + 'verbose_name': 'User login log', + 'ordering': ['-datetime', 'username'], + }, + ), + migrations.CreateModel( + name='UserSession', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('ip', models.GenericIPAddressField(verbose_name='Login IP')), + ('key', models.CharField(max_length=128, verbose_name='Session key')), + ('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')), + ('user_agent', models.CharField(blank=True, max_length=254, null=True, verbose_name='User agent')), + ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, verbose_name='Login type')), + ('backend', models.CharField(default='', max_length=32, verbose_name='Auth backend')), + ('date_created', models.DateTimeField(blank=True, null=True, verbose_name='Login date')), + ], + options={ + 'verbose_name': 'User session', + 'ordering': ['-date_created'], + 'permissions': [('offline_usersession', 'Offline user session')], + }, ), ] diff --git a/apps/audits/migrations/0002_ftplog_org_id.py b/apps/audits/migrations/0002_ftplog_org_id.py index 0c45da926..e571a26a3 100644 --- a/apps/audits/migrations/0002_ftplog_org_id.py +++ b/apps/audits/migrations/0002_ftplog_org_id.py @@ -1,18 +1,28 @@ -# Generated by Django 2.0.7 on 2018-08-07 03:16 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -from django.db import migrations, models +from django.db import migrations class Migration(migrations.Migration): + initial = True + dependencies = [ + ('ops', '0001_initial'), ('audits', '0001_initial'), ] operations = [ - migrations.AddField( - model_name='ftplog', - name='org_id', - field=models.CharField(blank=True, db_index=True, default=None, max_length=36, null=True), + migrations.CreateModel( + name='JobLog', + fields=[ + ], + options={ + 'verbose_name': 'Job audit log', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('ops.jobexecution',), ), ] diff --git a/apps/audits/migrations/0003_auto_20180816_1652.py b/apps/audits/migrations/0003_auto_20180816_1652.py index fe5cd806d..b3908a2e4 100644 --- a/apps/audits/migrations/0003_auto_20180816_1652.py +++ b/apps/audits/migrations/0003_auto_20180816_1652.py @@ -1,18 +1,23 @@ -# Generated by Django 2.0.7 on 2018-08-16 08:52 +# Generated by Django 4.1.13 on 2024-05-09 03:16 +from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ ('audits', '0002_ftplog_org_id'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AlterField( - model_name='ftplog', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), + migrations.AddField( + model_name='usersession', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to=settings.AUTH_USER_MODEL, verbose_name='User'), ), ] diff --git a/apps/audits/migrations/0004_operatelog_passwordchangelog_userloginlog.py b/apps/audits/migrations/0004_operatelog_passwordchangelog_userloginlog.py deleted file mode 100644 index a6002abca..000000000 --- a/apps/audits/migrations/0004_operatelog_passwordchangelog_userloginlog.py +++ /dev/null @@ -1,41 +0,0 @@ -# Generated by Django 2.1 on 2018-09-03 03:32 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0014_auto_20180816_1652'), - ('audits', '0003_auto_20180816_1652'), - ] - - operations = [ - migrations.CreateModel( - name='OperateLog', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('user', models.CharField(max_length=128, verbose_name='User')), - ('action', models.CharField(choices=[('create', 'Create'), ('update', 'Update'), ('delete', 'Delete')], max_length=16, verbose_name='Action')), - ('resource_type', models.CharField(max_length=64, verbose_name='Resource Type')), - ('resource', models.CharField(max_length=128, verbose_name='Resource')), - ('remote_addr', models.CharField(blank=True, max_length=15, null=True, verbose_name='Remote addr')), - ('datetime', models.DateTimeField(auto_now=True)), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='PasswordChangeLog', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('user', models.CharField(max_length=128, verbose_name='User')), - ('change_by', models.CharField(max_length=128, verbose_name='Change by')), - ('remote_addr', models.CharField(blank=True, max_length=15, null=True, verbose_name='Remote addr')), - ('datetime', models.DateTimeField(auto_now=True)), - ], - ), - ] diff --git a/apps/audits/migrations/0005_auto_20190228_1715.py b/apps/audits/migrations/0005_auto_20190228_1715.py deleted file mode 100644 index aac747e9b..000000000 --- a/apps/audits/migrations/0005_auto_20190228_1715.py +++ /dev/null @@ -1,55 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-28 09:15 - -import uuid - -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('audits', '0004_operatelog_passwordchangelog_userloginlog'), - ('users', '0019_auto_20190304_1459'), - ] - state_operations = [ - migrations.CreateModel( - name='UserLoginLog', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, - serialize=False)), - ('username', - models.CharField(max_length=128, verbose_name='Username')), - ('type', - models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], - max_length=2, verbose_name='Login type')), - ('ip', models.GenericIPAddressField(verbose_name='Login IP')), - ('city', models.CharField(blank=True, max_length=254, null=True, - verbose_name='Login city')), - ('user_agent', - models.CharField(blank=True, max_length=254, null=True, - verbose_name='User agent')), - ('mfa', models.SmallIntegerField( - choices=[(0, 'Disabled'), (1, 'Enabled'), (2, '-')], - default=2, verbose_name='MFA')), - ('reason', models.SmallIntegerField( - choices=[(0, '-'), (1, 'Username/password check failed'), - (2, 'MFA authentication failed'), - (3, 'Username does not exist'), - (4, 'Password expired')], default=0, - verbose_name='Reason')), - ('status', models.BooleanField( - choices=[(True, 'Success'), (False, 'Failed')], - default=True, max_length=2, verbose_name='Status')), - ('datetime', - models.DateTimeField(default=django.utils.timezone.now, - verbose_name='Date login')), - ], - options={ - 'ordering': ['-datetime', 'username'], - }, - ), - ] - - operations = [ - migrations.SeparateDatabaseAndState(state_operations=state_operations) - ] diff --git a/apps/audits/migrations/0006_auto_20190726_1753.py b/apps/audits/migrations/0006_auto_20190726_1753.py deleted file mode 100644 index beb382c31..000000000 --- a/apps/audits/migrations/0006_auto_20190726_1753.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-26 09:53 - -from django.db import migrations, models - - -def migrate_loginlog_reason_to_str(apps, schema_editor): - db_alias = schema_editor.connection.alias - - reason_map = { - "0": "", - "1": 'Username/password check failed', - "2": 'MFA authentication failed', - "3": "Username does not exist", - "4": "Password expired", - } - - model = apps.get_model("audits", "UserLoginLog") - for k, v in reason_map.items(): - model.objects.using(db_alias).filter(reason=k).update(reason=v) - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0005_auto_20190228_1715'), - ] - - operations = [ - migrations.AlterField( - model_name='userloginlog', - name='reason', - field=models.CharField(blank=True, default='', max_length=128, verbose_name='Reason'), - ), - migrations.RunPython(migrate_loginlog_reason_to_str), - ] diff --git a/apps/audits/migrations/0007_auto_20191202_1010.py b/apps/audits/migrations/0007_auto_20191202_1010.py deleted file mode 100644 index 3c355ff69..000000000 --- a/apps/audits/migrations/0007_auto_20191202_1010.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-02 02:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0006_auto_20190726_1753'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr'), - ), - migrations.AlterField( - model_name='operatelog', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr'), - ), - migrations.AlterField( - model_name='passwordchangelog', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr'), - ), - ] diff --git a/apps/audits/migrations/0008_auto_20200508_2105.py b/apps/audits/migrations/0008_auto_20200508_2105.py deleted file mode 100644 index bde6687ba..000000000 --- a/apps/audits/migrations/0008_auto_20200508_2105.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2.10 on 2020-05-08 13:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0007_auto_20191202_1010'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='date_start', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date start'), - ), - migrations.AlterField( - model_name='operatelog', - name='datetime', - field=models.DateTimeField(auto_now=True, verbose_name='Datetime'), - ), - migrations.AlterField( - model_name='passwordchangelog', - name='datetime', - field=models.DateTimeField(auto_now=True, verbose_name='Datetime'), - ), - ] diff --git a/apps/audits/migrations/0009_auto_20200624_1654.py b/apps/audits/migrations/0009_auto_20200624_1654.py deleted file mode 100644 index 6630558cf..000000000 --- a/apps/audits/migrations/0009_auto_20200624_1654.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-06-24 08:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0008_auto_20200508_2105'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='operate', - field=models.CharField(choices=[('Delete', 'Delete'), ('Upload', 'Upload'), ('Download', 'Download'), ('Rmdir', 'Rmdir'), ('Rename', 'Rename'), ('Mkdir', 'Mkdir'), ('Symlink', 'Symlink')], max_length=16, verbose_name='Operate'), - ), - ] diff --git a/apps/audits/migrations/0010_auto_20200811_1122.py b/apps/audits/migrations/0010_auto_20200811_1122.py deleted file mode 100644 index f274bf815..000000000 --- a/apps/audits/migrations/0010_auto_20200811_1122.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-11 03:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0009_auto_20200624_1654'), - ] - - operations = [ - migrations.AlterField( - model_name='operatelog', - name='datetime', - field=models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime'), - ), - ] diff --git a/apps/audits/migrations/0011_userloginlog_backend.py b/apps/audits/migrations/0011_userloginlog_backend.py deleted file mode 100644 index 4e82d7dda..000000000 --- a/apps/audits/migrations/0011_userloginlog_backend.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2020-12-09 03:03 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0010_auto_20200811_1122'), - ] - - operations = [ - migrations.AddField( - model_name='userloginlog', - name='backend', - field=models.CharField(default='', max_length=32, verbose_name='Authentication backend'), - ), - ] diff --git a/apps/audits/migrations/0012_auto_20210414_1443.py b/apps/audits/migrations/0012_auto_20210414_1443.py deleted file mode 100644 index 39a8ac52c..000000000 --- a/apps/audits/migrations/0012_auto_20210414_1443.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-04-14 06:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0011_userloginlog_backend'), - ] - - operations = [ - migrations.AlterField( - model_name='userloginlog', - name='type', - field=models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, verbose_name='Login type'), - ), - ] diff --git a/apps/audits/migrations/0013_auto_20211130_1037.py b/apps/audits/migrations/0013_auto_20211130_1037.py deleted file mode 100644 index 15fa2a382..000000000 --- a/apps/audits/migrations/0013_auto_20211130_1037.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.1.13 on 2021-11-30 02:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0012_auto_20210414_1443'), - ] - - operations = [ - migrations.AlterModelOptions( - name='ftplog', - options={'verbose_name': 'File transfer log'}, - ), - migrations.AlterModelOptions( - name='operatelog', - options={'verbose_name': 'Operate log'}, - ), - migrations.AlterModelOptions( - name='passwordchangelog', - options={'verbose_name': 'Password change log'}, - ), - migrations.AlterModelOptions( - name='userloginlog', - options={'ordering': ['-datetime', 'username'], 'verbose_name': 'User login log'}, - ), - ] diff --git a/apps/audits/migrations/0014_auto_20220505_1902.py b/apps/audits/migrations/0014_auto_20220505_1902.py deleted file mode 100644 index 8c483560c..000000000 --- a/apps/audits/migrations/0014_auto_20220505_1902.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.14 on 2022-05-05 11:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0013_auto_20211130_1037'), - ] - - operations = [ - migrations.AlterField( - model_name='operatelog', - name='action', - field=models.CharField(choices=[('create', 'Create'), ('view', 'View'), ('update', 'Update'), ('delete', 'Delete')], max_length=16, verbose_name='Action'), - ), - ] diff --git a/apps/audits/migrations/0015_auto_20221011_1745.py b/apps/audits/migrations/0015_auto_20221011_1745.py deleted file mode 100644 index dafd35dc8..000000000 --- a/apps/audits/migrations/0015_auto_20221011_1745.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.14 on 2022-10-11 09:45 - -import common.db.encoder -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0014_auto_20220505_1902'), - ] - - operations = [ - migrations.AddField( - model_name='operatelog', - name='after', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True), - ), - migrations.AddField( - model_name='operatelog', - name='before', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True), - ), - ] diff --git a/apps/audits/migrations/0016_auto_20221111_1919.py b/apps/audits/migrations/0016_auto_20221111_1919.py deleted file mode 100644 index 226588e7b..000000000 --- a/apps/audits/migrations/0016_auto_20221111_1919.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-11 11:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('audits', '0015_auto_20221011_1745'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='operate', - field=models.CharField( - choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'), - ('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download')], max_length=16, - verbose_name='Operate'), - ), - migrations.AlterField( - model_name='operatelog', - name='action', - field=models.CharField(choices=[ - ('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), - ('create', 'Create'), ('connect', 'Connect'), ('login', 'Login'), - ('change_password', 'Change password') - ], max_length=16, verbose_name='Action'), - ), - migrations.AlterField( - model_name='userloginlog', - name='status', - field=models.BooleanField(choices=[(1, 'Success'), (0, 'Failed')], default=1, verbose_name='Status'), - ), - ] diff --git a/apps/audits/migrations/0017_auto_20221220_1757.py b/apps/audits/migrations/0017_auto_20221220_1757.py deleted file mode 100644 index b879648e8..000000000 --- a/apps/audits/migrations/0017_auto_20221220_1757.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 09:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('audits', '0016_auto_20221111_1919'), - ] - - operations = [ - migrations.RenameField( - model_name='ftplog', - old_name='system_user', - new_name='account', - ), - migrations.AlterField( - model_name='ftplog', - name='account', - field=models.CharField(default='', max_length=128, verbose_name='Account'), - preserve_default=False, - ), - ] diff --git a/apps/audits/migrations/0018_operatelog_resource_id.py b/apps/audits/migrations/0018_operatelog_resource_id.py deleted file mode 100644 index 9e99e1e3f..000000000 --- a/apps/audits/migrations/0018_operatelog_resource_id.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.14 on 2023-01-03 08:53 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0017_auto_20221220_1757'), - ] - - operations = [ - migrations.AddField( - model_name='operatelog', - name='resource_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Resource'), - ), - migrations.AlterModelOptions( - name='operatelog', - options={'ordering': ('-datetime',), 'verbose_name': 'Operate log'}, - ), - ] diff --git a/apps/audits/migrations/0019_alter_operatelog_options.py b/apps/audits/migrations/0019_alter_operatelog_options.py deleted file mode 100644 index 2039fb221..000000000 --- a/apps/audits/migrations/0019_alter_operatelog_options.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0018_operatelog_resource_id'), - ] - - operations = [ - ] diff --git a/apps/audits/migrations/0020_auto_20230117_1004.py b/apps/audits/migrations/0020_auto_20230117_1004.py deleted file mode 100644 index 4270b0642..000000000 --- a/apps/audits/migrations/0020_auto_20230117_1004.py +++ /dev/null @@ -1,50 +0,0 @@ -# Generated by Django 3.2.14 on 2023-01-17 02:04 - -import common.db.encoder -from django.db import migrations, models - -from audits.backends.db import OperateLogStore - - -def migrate_operate_log_after_before(apps, schema_editor): - operate_log_model = apps.get_model("audits", "OperateLog") - db_alias = schema_editor.connection.alias - count, batch_size = 0, 1000 - - while True: - operate_logs = [] - queryset = operate_log_model.objects.using(db_alias).all()[count:count + batch_size] - if not queryset: - break - count += len(queryset) - for inst in queryset: - before, after, diff = inst.before, inst.after, dict() - if not any([before, after]): - continue - diff = OperateLogStore.convert_before_after_to_diff(before, after) - inst.diff = diff - operate_logs.append(inst) - operate_log_model.objects.bulk_update(operate_logs, ['diff']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0019_alter_operatelog_options'), - ] - - operations = [ - migrations.AddField( - model_name='operatelog', - name='diff', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True), - ), - migrations.RunPython(migrate_operate_log_after_before), - migrations.RemoveField(model_name='operatelog', name='after', ), - migrations.RemoveField(model_name='operatelog', name='before', ), - migrations.AlterField( - model_name='operatelog', - name='resource_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=128, verbose_name='Resource'), - ), - ] diff --git a/apps/audits/migrations/0021_auto_20230207_0857.py b/apps/audits/migrations/0021_auto_20230207_0857.py deleted file mode 100644 index 4e66c63f0..000000000 --- a/apps/audits/migrations/0021_auto_20230207_0857.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-07 00:57 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0020_auto_20230117_1004'), - ('ops', '0023_auto_20220912_0021'), - ] - - operations = [ - migrations.CreateModel( - name='ActivityLog', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('type', models.CharField(choices=[('O', 'Operate log'), ('S', 'Session log'), ('L', 'Login log'), ('T', 'Task')], default=None, max_length=2, null=True, verbose_name='Activity type')), - ('resource_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Resource')), - ('datetime', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime')), - ('detail', models.TextField(blank=True, default='', verbose_name='Detail')), - ('detail_id', models.CharField(default=None, max_length=36, null=True, verbose_name='Detail ID')), - ], - options={ - 'verbose_name': 'Activity log', - 'ordering': ('-datetime',), - }, - ), - migrations.CreateModel( - name='JobLog', - fields=[ - ], - options={ - 'verbose_name': 'Job audit log', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('ops.jobexecution',), - ), - ] diff --git a/apps/audits/migrations/0022_auto_20230605_1555.py b/apps/audits/migrations/0022_auto_20230605_1555.py deleted file mode 100644 index c5ec8847f..000000000 --- a/apps/audits/migrations/0022_auto_20230605_1555.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-05 07:55 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0021_auto_20230207_0857'), - ] - - operations = [ - migrations.AddField( - model_name='ftplog', - name='has_file', - field=models.BooleanField(default=False, verbose_name='File'), - ), - migrations.AddField( - model_name='ftplog', - name='session', - field=models.CharField(default=uuid.uuid4, max_length=36, verbose_name='Session'), - ), - migrations.AlterField( - model_name='ftplog', - name='operate', - field=models.CharField(choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'), ('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download'), ('rename_dir', 'Rename dir')], max_length=16, verbose_name='Operate'), - ), - ] diff --git a/apps/audits/migrations/0023_auto_20230906_1322.py b/apps/audits/migrations/0023_auto_20230906_1322.py deleted file mode 100644 index 34998318c..000000000 --- a/apps/audits/migrations/0023_auto_20230906_1322.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-06 05:31 - -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0022_auto_20230605_1555'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='date_start', - field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date start'), - ), - migrations.AlterField( - model_name='operatelog', - name='action', - field=models.CharField(choices=[('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), ('create', 'Create'), ('download', 'Download'), ('connect', 'Connect'), ('login', 'Login'), ('change_password', 'Change password'), ('accept', 'Accept'), ('review', 'Review'), ('notice', 'Notifications'), ('reject', 'Reject'), ('approve', 'Approve'), ('close', 'Close')], max_length=16, verbose_name='Action'), - ), - migrations.AlterField( - model_name='userloginlog', - name='datetime', - field=models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date login'), - ), - ] diff --git a/apps/audits/migrations/0024_usersession.py b/apps/audits/migrations/0024_usersession.py deleted file mode 100644 index c5a6c9331..000000000 --- a/apps/audits/migrations/0024_usersession.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-15 08:58 - -import uuid - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('audits', '0023_auto_20230906_1322'), - ] - - operations = [ - migrations.CreateModel( - name='UserSession', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('ip', models.GenericIPAddressField(verbose_name='Login IP')), - ('key', models.CharField(max_length=128, verbose_name='Session key')), - ('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')), - ('user_agent', models.CharField(blank=True, max_length=254, null=True, verbose_name='User agent')), - ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, verbose_name='Login type')), - ('backend', models.CharField(default='', max_length=32, verbose_name='Authentication backend')), - ('date_created', models.DateTimeField(blank=True, null=True, verbose_name='Date created')), - ('date_expired', models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='Date expired')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'User session', - 'ordering': ['-date_created'], - 'permissions': [('offline_usersession', 'Offline user session')], - }, - ), - ] diff --git a/apps/audits/migrations/0025_remove_usersession_date_expired.py b/apps/audits/migrations/0025_remove_usersession_date_expired.py deleted file mode 100644 index 0b495f72d..000000000 --- a/apps/audits/migrations/0025_remove_usersession_date_expired.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-18 08:01 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0024_usersession'), - ] - - operations = [ - migrations.RemoveField( - model_name='usersession', - name='date_expired', - ), - ] diff --git a/apps/audits/models.py b/apps/audits/models.py index 762147c98..a06724803 100644 --- a/apps/audits/models.py +++ b/apps/audits/models.py @@ -63,7 +63,7 @@ class FTPLog(OrgModelMixin): filename = models.CharField(max_length=1024, verbose_name=_("Filename")) is_success = models.BooleanField(default=True, verbose_name=_("Success")) date_start = models.DateTimeField(auto_now_add=True, verbose_name=_("Date start"), db_index=True) - has_file = models.BooleanField(default=False, verbose_name=_("File")) + has_file = models.BooleanField(default=False, verbose_name=_("Can Download")) session = models.CharField(max_length=36, verbose_name=_("Session"), default=uuid.uuid4) class Meta: @@ -207,9 +207,9 @@ class UserLoginLog(models.Model): choices=LoginStatusChoices.choices, verbose_name=_("Status"), ) - datetime = models.DateTimeField(default=timezone.now, verbose_name=_("Date login"), db_index=True) + datetime = models.DateTimeField(default=timezone.now, verbose_name=_("Login Date"), db_index=True) backend = models.CharField( - max_length=32, default="", verbose_name=_("Authentication backend") + max_length=32, default="", verbose_name=_("Auth backend") ) def __str__(self): @@ -265,8 +265,8 @@ class UserSession(models.Model): city = models.CharField(max_length=254, blank=True, null=True, verbose_name=_("Login city")) user_agent = models.CharField(max_length=254, blank=True, null=True, verbose_name=_("User agent")) type = models.CharField(choices=LoginTypeChoices.choices, max_length=2, verbose_name=_("Login type")) - backend = models.CharField(max_length=32, default="", verbose_name=_("Authentication backend")) - date_created = models.DateTimeField(null=True, blank=True, verbose_name=_('Date created')) + backend = models.CharField(max_length=32, default="", verbose_name=_("Auth backend")) + date_created = models.DateTimeField(null=True, blank=True, verbose_name=_('Login date')) user = models.ForeignKey( 'users.User', verbose_name=_('User'), related_name='sessions', on_delete=models.CASCADE ) diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py index 3111b0d99..d2a019e4c 100644 --- a/apps/audits/serializers.py +++ b/apps/audits/serializers.py @@ -67,7 +67,7 @@ class UserLoginLogSerializer(serializers.ModelSerializer): extra_kwargs = { "user_agent": {"label": _("User agent")}, "reason_display": {"label": _("Reason display")}, - "backend_display": {"label": _("Authentication backend")}, + "backend_display": {"label": _("Auth backend display")}, } @@ -131,7 +131,7 @@ class ActivityUnionLogSerializer(serializers.Serializer): def get_content(obj): if not obj['r_detail']: action = obj['r_action'].replace('_', ' ').capitalize() - ctn = _('User %s %s this resource') % (obj['r_user'], _(action)) + ctn = _('%s %s this resource') % (obj['r_user'], _(action).lower()) else: ctn = i18n_trans(obj['r_detail']) return ctn @@ -181,7 +181,7 @@ class UserSessionSerializer(serializers.ModelSerializer): ] fields = fields_small extra_kwargs = { - "backend_display": {"label": _("Authentication backend")}, + "backend_display": {"label": _("Auth backend display")}, } def get_is_current_user_session(self, obj): diff --git a/apps/audits/signal_handlers/login_log.py b/apps/audits/signal_handlers/login_log.py index cdcf244cb..11000830b 100644 --- a/apps/audits/signal_handlers/login_log.py +++ b/apps/audits/signal_handlers/login_log.py @@ -128,7 +128,6 @@ def on_user_auth_success(sender, user, request, login_type=None, **kwargs): request.session['login_time'] = data['datetime'].strftime('%Y-%m-%d %H:%M:%S') data.update({'mfa': int(user.mfa_enabled), 'status': True}) instance = write_login_log(**data) - create_user_session(request, user.id, instance) request.session['user_log_id'] = str(instance.id) request.session['can_send_notifications'] = True diff --git a/apps/audits/tasks.py b/apps/audits/tasks.py index ac28e91cb..00383544a 100644 --- a/apps/audits/tasks.py +++ b/apps/audits/tasks.py @@ -92,6 +92,22 @@ def batch_delete(queryset, batch_size=3000): model.objects.filter(id__in=list(pks)).delete() +def remove_files_by_days(root_path, days, file_types=None): + if file_types is None: + file_types = ['.json', '.tar', '.gz', '.mp4'] + need_rm_files = [] + expire_date = timezone.now() - timezone.timedelta(days=days) + timestamp = expire_date.timestamp() + for root, dirs, files in os.walk(root_path): + for file in files: + if any(file.endswith(file_type) for file_type in file_types): + file_path = os.path.join(root, file) + if os.path.getmtime(file_path) <= timestamp: + need_rm_files.append(file_path) + for file in need_rm_files: + os.remove(file) + + def clean_expired_session_period(): logger.info("Start clean expired session record, commands and replay") days = get_log_keep_day('TERMINAL_SESSION_KEEP_DURATION') @@ -105,10 +121,7 @@ def clean_expired_session_period(): logger.info("Clean session item done") batch_delete(expired_commands) logger.info("Clean session command done") - command = "find %s -mtime +%s \\( -name '*.json' -o -name '*.tar' -o -name '*.gz' \\) -exec rm -f {} \\;" % ( - replay_dir, days - ) - subprocess.call(command, shell=True) + remove_files_by_days(replay_dir, days) command = "find %s -type d -empty -delete;" % replay_dir subprocess.call(command, shell=True) logger.info("Clean session replay done") diff --git a/apps/authentication/apps.py b/apps/authentication/apps.py index 5a1c1966a..8f9c38c94 100644 --- a/apps/authentication/apps.py +++ b/apps/authentication/apps.py @@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _ class AuthenticationConfig(AppConfig): name = 'authentication' - verbose_name = _('Authentication') + verbose_name = _('App Authentication') def ready(self): from . import signal_handlers # noqa diff --git a/apps/authentication/backends/passkey/fido.py b/apps/authentication/backends/passkey/fido.py index 636b0bb79..4a0ebc034 100644 --- a/apps/authentication/backends/passkey/fido.py +++ b/apps/authentication/backends/passkey/fido.py @@ -109,7 +109,10 @@ def register_complete(request): data = request.data server = get_server(request) state = request.session.pop("fido2_state") - auth_data = server.register_complete(state, response=data) + try: + auth_data = server.register_complete(state, response=data) + except ValueError as e: + raise ValidationError({'error': str(e)}) encoded = websafe_encode(auth_data.credential_data) platform = get_current_platform(request) name = data.pop("key_name", '') or platform diff --git a/apps/authentication/backends/saml2/views.py b/apps/authentication/backends/saml2/views.py index 235dd2c38..bbc3b600b 100644 --- a/apps/authentication/backends/saml2/views.py +++ b/apps/authentication/backends/saml2/views.py @@ -50,7 +50,7 @@ class PrepareRequestMixin: if idp_metadata_xml.strip(): xml_idp_settings = IdPMetadataParse.parse(idp_metadata_xml) except Exception as err: - logger.warning('Failed to get IDP metadata XML settings, error: %s', str(err)) + logger.warning('Failed to get IDP Metadata XML settings, error: %s', str(err)) url_idp_settings = None try: @@ -59,7 +59,7 @@ class PrepareRequestMixin: idp_metadata_url, timeout=20 ) except Exception as err: - logger.warning('Failed to get IDP metadata URL settings, error: %s', str(err)) + logger.warning('Failed to get IDP Metadata URL settings, error: %s', str(err)) idp_settings = url_idp_settings or xml_idp_settings @@ -231,7 +231,7 @@ class Saml2EndSessionView(View, PrepareRequestMixin): if settings.SAML2_LOGOUT_COMPLETELY: saml_instance = self.init_saml_auth(request) - logger.debug(log_prompt.format('Log out IDP user session synchronously')) + logger.debug(log_prompt.format('Logout IDP user session synchronously')) return HttpResponseRedirect(saml_instance.logout()) logger.debug(log_prompt.format('Redirect logout url')) diff --git a/apps/authentication/errors/failed.py b/apps/authentication/errors/failed.py index 729d93b6d..9b93242e2 100644 --- a/apps/authentication/errors/failed.py +++ b/apps/authentication/errors/failed.py @@ -142,11 +142,11 @@ class ACLError(AuthFailedNeedLogMixin, AuthFailedError): } -class LoginACLIPAndTimePeriodNotAllowed(ACLError): +class LoginACLNotAllowed(ACLError): def __init__(self, username, request, **kwargs): self.username = username self.request = request - super().__init__(_("Current IP and Time period is not allowed"), **kwargs) + super().__init__(_("Current login is prohibited by ACL rules"), **kwargs) class MFACodeRequiredError(AuthFailedError): diff --git a/apps/authentication/forms.py b/apps/authentication/forms.py index 05d102e8e..d7a1df484 100644 --- a/apps/authentication/forms.py +++ b/apps/authentication/forms.py @@ -30,13 +30,13 @@ class UserLoginForm(forms.Form): ) auto_login = forms.BooleanField( required=False, initial=False, - widget=forms.CheckboxInput() + widget=forms.CheckboxInput(), + label=_('Auto-login') ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) auto_login_field = self.fields['auto_login'] - auto_login_field.label = _("Auto login") if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE: auto_login_field.widget = forms.HiddenInput() diff --git a/apps/authentication/mfa/sms.py b/apps/authentication/mfa/sms.py index d114b648e..7cf71985e 100644 --- a/apps/authentication/mfa/sms.py +++ b/apps/authentication/mfa/sms.py @@ -44,13 +44,13 @@ class MFASms(BaseMFA): return settings.SMS_ENABLED def get_enable_url(self) -> str: - return '/ui/#/profile/setting?activeTab=ProfileUpdate' + return '/ui/#/profile/index' def can_disable(self) -> bool: return True def disable(self): - return '/ui/#/profile/setting?activeTab=ProfileUpdate' + return '/ui/#/profile/index' @staticmethod def help_text_of_enable(): @@ -61,4 +61,4 @@ class MFASms(BaseMFA): return _("Clear phone number to disable") def get_disable_url(self) -> str: - return '/ui/#/profile/setting?activeTab=ProfileUpdate' + return '/ui/#/profile/index' diff --git a/apps/authentication/migrations/0001_initial.py b/apps/authentication/migrations/0001_initial.py index 4c2251138..7b332051f 100644 --- a/apps/authentication/migrations/0001_initial.py +++ b/apps/authentication/migrations/0001_initial.py @@ -1,9 +1,9 @@ -# Generated by Django 2.1.7 on 2019-02-28 08:07 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import common.db.models -from django.conf import settings +import authentication.models.access_key +import authentication.models.connection_token +import common.db.fields from django.db import migrations, models -import django.db.models.deletion import uuid @@ -12,46 +12,116 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('users', '0019_auto_20190304_1459'), ] - state_operations = [ + operations = [ migrations.CreateModel( name='AccessKey', fields=[ - ('id', - models.UUIDField(default=uuid.uuid4, editable=False, - primary_key=True, serialize=False, - verbose_name='AccessKeyID')), - ('secret', - models.UUIDField(default=uuid.uuid4, editable=False, - verbose_name='AccessKeySecret')), - ('user', models.ForeignKey( - on_delete=common.db.models.CASCADE_SIGNAL_SKIP, - related_name='access_keys', - to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='AccessKeyID')), + ('secret', models.CharField(default=authentication.models.access_key.default_secret, max_length=36, verbose_name='AccessKeySecret')), + ('ip_group', models.JSONField(default=authentication.models.access_key.default_ip_group, verbose_name='IP group')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('date_last_used', models.DateTimeField(blank=True, null=True, verbose_name='Date last used')), + ('date_created', models.DateTimeField(auto_now_add=True)), ], + options={ + 'verbose_name': 'Access key', + }, + ), + migrations.CreateModel( + name='ConnectionToken', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('value', models.CharField(default='', max_length=64, verbose_name='Value')), + ('account', models.CharField(max_length=128, verbose_name='Account name')), + ('input_username', models.CharField(blank=True, default='', max_length=128, verbose_name='Input username')), + ('input_secret', common.db.fields.EncryptTextField(blank=True, default='', max_length=64, verbose_name='Input secret')), + ('protocol', models.CharField(default='ssh', max_length=16, verbose_name='Protocol')), + ('connect_method', models.CharField(max_length=32, verbose_name='Connect method')), + ('connect_options', models.JSONField(default=dict, verbose_name='Connect options')), + ('user_display', models.CharField(default='', max_length=128, verbose_name='User display')), + ('asset_display', models.CharField(default='', max_length=128, verbose_name='Asset display')), + ('is_reusable', models.BooleanField(default=False, verbose_name='Reusable')), + ('date_expired', models.DateTimeField(default=authentication.models.connection_token.date_expired_default, verbose_name='Date expired')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ], + options={ + 'verbose_name': 'Connection token', + 'ordering': ('-date_expired',), + 'permissions': [('expire_connectiontoken', 'Can expire connection token'), ('reuse_connectiontoken', 'Can reuse connection token')], + }, + ), + migrations.CreateModel( + name='Passkey', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('is_active', models.BooleanField(default=True, verbose_name='Enabled')), + ('platform', models.CharField(default='', max_length=255, verbose_name='Platform')), + ('added_on', models.DateTimeField(auto_now_add=True, verbose_name='Added on')), + ('date_last_used', models.DateTimeField(default=None, null=True, verbose_name='Date last used')), + ('credential_id', models.CharField(max_length=255, unique=True, verbose_name='Credential ID')), + ('token', models.CharField(max_length=255, verbose_name='Token')), + ], + options={ + 'abstract': False, + }, ), migrations.CreateModel( name='PrivateToken', fields=[ - ('key', - models.CharField(max_length=40, primary_key=True, - serialize=False, verbose_name='Key')), - ('created', models.DateTimeField(auto_now_add=True, - verbose_name='Created')), - ('user', models.OneToOneField( - on_delete=django.db.models.deletion.CASCADE, - related_name='auth_token', - to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), + ('date_last_used', models.DateTimeField(blank=True, null=True, verbose_name='Date last used')), ], options={ 'verbose_name': 'Private Token', }, ), - ] - - operations = [ - migrations.SeparateDatabaseAndState(state_operations=state_operations) + migrations.CreateModel( + name='SSOToken', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('authkey', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='Token')), + ('expired', models.BooleanField(default=False, verbose_name='Expired')), + ], + options={ + 'verbose_name': 'SSO token', + }, + ), + migrations.CreateModel( + name='TempToken', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('username', models.CharField(max_length=128, verbose_name='Username')), + ('secret', models.CharField(max_length=64, verbose_name='Secret')), + ('verified', models.BooleanField(default=False, verbose_name='Verified')), + ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), + ('date_expired', models.DateTimeField(verbose_name='Date expired')), + ], + options={ + 'verbose_name': 'Temporary token', + }, + ), ] diff --git a/apps/authentication/migrations/0002_auto_20190729_1423.py b/apps/authentication/migrations/0002_auto_20190729_1423.py index 6e971e96b..7a35c0105 100644 --- a/apps/authentication/migrations/0002_auto_20190729_1423.py +++ b/apps/authentication/migrations/0002_auto_20190729_1423.py @@ -1,23 +1,69 @@ -# Generated by Django 2.1.7 on 2019-07-29 06:23 +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.models +from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + + initial = True + dependencies = [ + ('assets', '0002_auto_20180105_1807'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('tickets', '0001_initial'), ('authentication', '0001_initial'), ] operations = [ migrations.AddField( - model_name='accesskey', - name='date_created', - field=models.DateTimeField(auto_now_add=True), - preserve_default=False, + model_name='ssotoken', + name='user', + field=models.ForeignKey(db_constraint=False, on_delete=common.db.models.CASCADE_SIGNAL_SKIP, to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.AddField( + model_name='privatetoken', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token', to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.AddField( + model_name='passkey', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='connectiontoken', + name='asset', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_tokens', to='assets.asset', verbose_name='Asset'), + ), + migrations.AddField( + model_name='connectiontoken', + name='from_ticket', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_token', to='tickets.applyloginassetticket', verbose_name='From ticket'), + ), + migrations.AddField( + model_name='connectiontoken', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_tokens', to=settings.AUTH_USER_MODEL, verbose_name='User'), ), migrations.AddField( model_name='accesskey', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Active'), + name='user', + field=models.ForeignKey(on_delete=common.db.models.CASCADE_SIGNAL_SKIP, related_name='access_keys', to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.CreateModel( + name='SuperConnectionToken', + fields=[ + ], + options={ + 'verbose_name': 'Super connection token', + 'permissions': [('view_superconnectiontokensecret', 'Can view super connection token secret')], + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('authentication.connectiontoken',), ), ] diff --git a/apps/authentication/migrations/0003_loginconfirmsetting.py b/apps/authentication/migrations/0003_loginconfirmsetting.py deleted file mode 100644 index c8043bc87..000000000 --- a/apps/authentication/migrations/0003_loginconfirmsetting.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2.5 on 2019-10-31 10:23 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0002_auto_20190729_1423'), - ] - - operations = [ - migrations.CreateModel( - name='LoginConfirmSetting', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('reviewers', models.ManyToManyField(blank=True, related_name='review_login_confirm_settings', to=settings.AUTH_USER_MODEL, verbose_name='Reviewers')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='login_confirm_setting', to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/authentication/migrations/0004_ssotoken.py b/apps/authentication/migrations/0004_ssotoken.py deleted file mode 100644 index 57d2f9805..000000000 --- a/apps/authentication/migrations/0004_ssotoken.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-31 08:36 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0003_loginconfirmsetting'), - ] - - operations = [ - migrations.CreateModel( - name='SSOToken', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('authkey', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='Token')), - ('expired', models.BooleanField(default=False, verbose_name='Expired')), - ('user', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/authentication/migrations/0005_delete_loginconfirmsetting.py b/apps/authentication/migrations/0005_delete_loginconfirmsetting.py deleted file mode 100644 index cbf01a735..000000000 --- a/apps/authentication/migrations/0005_delete_loginconfirmsetting.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.1.12 on 2021-09-26 11:13 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0004_ssotoken'), - ] - - operations = [ - migrations.DeleteModel( - name='LoginConfirmSetting', - ), - ] diff --git a/apps/authentication/migrations/0006_auto_20211227_1059.py b/apps/authentication/migrations/0006_auto_20211227_1059.py deleted file mode 100644 index b01758bbd..000000000 --- a/apps/authentication/migrations/0006_auto_20211227_1059.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-27 02:59 - -import common.db.models -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0005_delete_loginconfirmsetting'), - ] - - operations = [ - migrations.AlterField( - model_name='ssotoken', - name='user', - field=models.ForeignKey(db_constraint=False, on_delete=common.db.models.CASCADE_SIGNAL_SKIP, to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - ] diff --git a/apps/authentication/migrations/0007_connectiontoken.py b/apps/authentication/migrations/0007_connectiontoken.py deleted file mode 100644 index 6c0b437da..000000000 --- a/apps/authentication/migrations/0007_connectiontoken.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.1.12 on 2022-02-11 06:01 -import uuid - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0006_auto_20211227_1059'), - ] - - operations = [ - migrations.CreateModel( - name='ConnectionToken', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False),), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ], - options={'verbose_name': 'Connection token'}, - ), - migrations.AlterModelOptions( - name='accesskey', - options={'verbose_name': 'Access key'}, - ), - migrations.AlterModelOptions( - name='ssotoken', - options={'verbose_name': 'SSO token'}, - ), - ] diff --git a/apps/authentication/migrations/0008_superconnectiontoken.py b/apps/authentication/migrations/0008_superconnectiontoken.py deleted file mode 100644 index 82e956a24..000000000 --- a/apps/authentication/migrations/0008_superconnectiontoken.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-02 11:53 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0007_connectiontoken'), - ] - - operations = [ - migrations.CreateModel( - name='SuperConnectionToken', - fields=[ - ], - options={ - 'verbose_name': 'Super connection token', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('authentication.connectiontoken',), - ), - ] diff --git a/apps/authentication/migrations/0009_auto_20220310_0616.py b/apps/authentication/migrations/0009_auto_20220310_0616.py deleted file mode 100644 index 652aa2ea4..000000000 --- a/apps/authentication/migrations/0009_auto_20220310_0616.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-09 22:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0008_superconnectiontoken'), - ] - - operations = [ - migrations.AlterModelOptions( - name='connectiontoken', - options={'permissions': [('view_connectiontokensecret', 'Can view connection token secret')], 'verbose_name': 'Connection token'}, - ), - ] diff --git a/apps/authentication/migrations/0010_temptoken.py b/apps/authentication/migrations/0010_temptoken.py deleted file mode 100644 index b76ae0f97..000000000 --- a/apps/authentication/migrations/0010_temptoken.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-08 07:04 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0009_auto_20220310_0616'), - ] - - operations = [ - migrations.CreateModel( - name='TempToken', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('username', models.CharField(max_length=128, verbose_name='Username')), - ('secret', models.CharField(max_length=64, verbose_name='Secret')), - ('verified', models.BooleanField(default=False, verbose_name='Verified')), - ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), - ('date_expired', models.DateTimeField(verbose_name='Date expired')), - ], - options={ - 'verbose_name': 'Temporary token', - }, - ), - ] diff --git a/apps/authentication/migrations/0011_auto_20220705_1940.py b/apps/authentication/migrations/0011_auto_20220705_1940.py deleted file mode 100644 index f965c9486..000000000 --- a/apps/authentication/migrations/0011_auto_20220705_1940.py +++ /dev/null @@ -1,92 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-05 11:40 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import authentication.models - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0021_auto_20220629_1826'), - ('assets', '0091_auto_20220629_1826'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0010_temptoken'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='application', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to='applications.application', - verbose_name='Application'), - ), - migrations.AddField( - model_name='connectiontoken', - name='application_display', - field=models.CharField(default='', max_length=128, verbose_name='Application display'), - ), - migrations.AddField( - model_name='connectiontoken', - name='asset', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to='assets.asset', verbose_name='Asset'), - ), - migrations.AddField( - model_name='connectiontoken', - name='asset_display', - field=models.CharField(default='', max_length=128, verbose_name='Asset display'), - ), - migrations.AddField( - model_name='connectiontoken', - name='date_expired', - field=models.DateTimeField(default=authentication.models.date_expired_default, verbose_name='Date expired'), - ), - migrations.AddField( - model_name='connectiontoken', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AddField( - model_name='connectiontoken', - name='secret', - field=models.CharField(default='', max_length=64, verbose_name='Secret'), - ), - migrations.AddField( - model_name='connectiontoken', - name='system_user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to='assets.systemuser', - verbose_name='System user'), - ), - migrations.AddField( - model_name='connectiontoken', - name='system_user_display', - field=models.CharField(default='', max_length=128, verbose_name='System user display'), - ), - migrations.AddField( - model_name='connectiontoken', - name='type', - field=models.CharField(choices=[('asset', 'Asset'), ('application', 'Application')], default='asset', - max_length=16, verbose_name='Type'), - ), - migrations.AddField( - model_name='connectiontoken', - name='user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AddField( - model_name='connectiontoken', - name='user_display', - field=models.CharField(default='', max_length=128, verbose_name='User display'), - ), - migrations.AlterModelOptions( - name='connectiontoken', - options={'ordering': ('-date_expired',), - 'permissions': [('view_connectiontokensecret', 'Can view connection token secret')], - 'verbose_name': 'Connection token'}, - ), - ] diff --git a/apps/authentication/migrations/0012_auto_20220816_1629.py b/apps/authentication/migrations/0012_auto_20220816_1629.py deleted file mode 100644 index 1557057c5..000000000 --- a/apps/authentication/migrations/0012_auto_20220816_1629.py +++ /dev/null @@ -1,59 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 08:29 - -from django.db import migrations, models - - -def migrate_system_user_to_account(apps, schema_editor): - connection_token_model = apps.get_model("authentication", "ConnectionToken") - count = 0 - bulk_size = 10000 - - while True: - connection_tokens = connection_token_model.objects \ - .prefetch_related('system_user')[count:bulk_size] - if not connection_tokens: - break - count += len(connection_tokens) - updated = [] - for connection_token in connection_tokens: - if not connection_token.system_user: - continue - connection_token.account_username = connection_token.system_user.username - updated.append(connection_token) - connection_token_model.objects.bulk_update(updated, ['account_username']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0011_auto_20220705_1940'), - ] - - operations = [ - migrations.RemoveField( - model_name='connectiontoken', - name='application', - ), - migrations.RemoveField( - model_name='connectiontoken', - name='application_display', - ), - migrations.RemoveField( - model_name='connectiontoken', - name='system_user_display', - ), - migrations.AddField( - model_name='connectiontoken', - name='account_username', - field=models.CharField(default='', max_length=128, verbose_name='Account'), - ), - migrations.RunPython(migrate_system_user_to_account), - migrations.RemoveField( - model_name='connectiontoken', - name='system_user', - ), - migrations.RemoveField( - model_name='connectiontoken', - name='type', - ), - ] diff --git a/apps/authentication/migrations/0013_connectiontoken_protocol.py b/apps/authentication/migrations/0013_connectiontoken_protocol.py deleted file mode 100644 index 3ba4785b0..000000000 --- a/apps/authentication/migrations/0013_connectiontoken_protocol.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.14 on 2022-10-27 12:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0012_auto_20220816_1629'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='protocol', - field=models.CharField(default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/authentication/migrations/0014_auto_20221122_2152.py b/apps/authentication/migrations/0014_auto_20221122_2152.py deleted file mode 100644 index 483b6d5f0..000000000 --- a/apps/authentication/migrations/0014_auto_20221122_2152.py +++ /dev/null @@ -1,51 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-22 13:52 - -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0013_connectiontoken_protocol'), - ] - - operations = [ - migrations.RenameField( - model_name='connectiontoken', - old_name='account_username', - new_name='account_name' - ), - migrations.AlterField( - model_name='connectiontoken', - name='account_name', - field=models.CharField(max_length=128, verbose_name='Account name'), - ), - migrations.AddField( - model_name='connectiontoken', - name='input_username', - field=models.CharField(blank=True, default='', max_length=128, verbose_name='Input username'), - ), - migrations.AddField( - model_name='connectiontoken', - name='input_secret', - field=common.db.fields.EncryptCharField(blank=True, default='', max_length=128, - verbose_name='Input secret'), - ), - migrations.RenameField( - model_name='connectiontoken', - old_name='secret', - new_name='value', - ), - migrations.AlterField( - model_name='connectiontoken', - name='value', - field=models.CharField(default='', max_length=64, verbose_name='Value'), - ), - migrations.AddField( - model_name='connectiontoken', - name='connect_method', - field=models.CharField(default='web_ui', max_length=32, verbose_name='Connect method'), - preserve_default=False, - ), - ] diff --git a/apps/authentication/migrations/0015_auto_20221205_1136.py b/apps/authentication/migrations/0015_auto_20221205_1136.py deleted file mode 100644 index 7de71fe5c..000000000 --- a/apps/authentication/migrations/0015_auto_20221205_1136.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-05 03:36 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0014_auto_20221122_2152'), - ] - - operations = [ - migrations.RenameField( - model_name='connectiontoken', - old_name='account_name', - new_name='account', - ), - ] diff --git a/apps/authentication/migrations/0016_auto_20221220_1956.py b/apps/authentication/migrations/0016_auto_20221220_1956.py deleted file mode 100644 index d1480629c..000000000 --- a/apps/authentication/migrations/0016_auto_20221220_1956.py +++ /dev/null @@ -1,58 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0015_auto_20221205_1136'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='ssotoken', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='temptoken', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='connectiontoken', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='connectiontoken', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='ssotoken', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='ssotoken', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='temptoken', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='temptoken', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - ] diff --git a/apps/authentication/migrations/0017_auto_20230105_1743.py b/apps/authentication/migrations/0017_auto_20230105_1743.py deleted file mode 100644 index f4f9bff69..000000000 --- a/apps/authentication/migrations/0017_auto_20230105_1743.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.2.14 on 2023-01-05 09:43 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0028_remove_app_tickets'), - ('authentication', '0016_auto_20221220_1956'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='from_ticket', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_token', to='tickets.applyloginassetticket', verbose_name='From ticket'), - ), - migrations.AddField( - model_name='connectiontoken', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Active'), - ), - ] diff --git a/apps/authentication/migrations/0018_alter_connectiontoken_input_secret.py b/apps/authentication/migrations/0018_alter_connectiontoken_input_secret.py deleted file mode 100644 index b11598066..000000000 --- a/apps/authentication/migrations/0018_alter_connectiontoken_input_secret.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-14 08:49 - -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0017_auto_20230105_1743'), - ] - - operations = [ - migrations.AlterField( - model_name='connectiontoken', - name='input_secret', - field=common.db.fields.EncryptTextField(blank=True, default='', max_length=64, verbose_name='Input secret'), - ), - ] diff --git a/apps/authentication/migrations/0019_connectiontoken_is_reusable.py b/apps/authentication/migrations/0019_connectiontoken_is_reusable.py deleted file mode 100644 index 92ccc892a..000000000 --- a/apps/authentication/migrations/0019_connectiontoken_is_reusable.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-08 07:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0018_alter_connectiontoken_input_secret'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='is_reusable', - field=models.BooleanField(default=False, verbose_name='Reusable'), - ), - ] diff --git a/apps/authentication/migrations/0020_connectiontoken_connect_options.py b/apps/authentication/migrations/0020_connectiontoken_connect_options.py deleted file mode 100644 index 15447c9b6..000000000 --- a/apps/authentication/migrations/0020_connectiontoken_connect_options.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-05 07:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0019_connectiontoken_is_reusable'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='connect_options', - field=models.JSONField(default=dict, verbose_name='Connect options'), - ), - ] diff --git a/apps/authentication/migrations/0021_auto_20230713_1459.py b/apps/authentication/migrations/0021_auto_20230713_1459.py deleted file mode 100644 index 03913f766..000000000 --- a/apps/authentication/migrations/0021_auto_20230713_1459.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.19 on 2023-07-13 06:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0020_connectiontoken_connect_options'), - ] - - operations = [ - migrations.AlterModelOptions( - name='connectiontoken', - options={'ordering': ('-date_expired',), - 'permissions': [('expire_connectiontoken', 'Can expire connection token'), - ('reuse_connectiontoken', 'Can reuse connection token')], - 'verbose_name': 'Connection token'}, - ), - migrations.AlterModelOptions( - name='superconnectiontoken', - options={'permissions': [('view_superconnectiontokensecret', 'Can view super connection token secret')], - 'verbose_name': 'Super connection token'}, - ), - ] diff --git a/apps/authentication/migrations/0022_passkey.py b/apps/authentication/migrations/0022_passkey.py deleted file mode 100644 index 322d5cf6f..000000000 --- a/apps/authentication/migrations/0022_passkey.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-08 08:10 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0021_auto_20230713_1459'), - ] - - operations = [ - migrations.CreateModel( - name='Passkey', - fields=[ - ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=255, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Enabled')), - ('platform', models.CharField(default='', max_length=255, verbose_name='Platform')), - ('added_on', models.DateTimeField(auto_now_add=True, verbose_name='Added on')), - ('date_last_used', models.DateTimeField(default=None, null=True, verbose_name='Date last used')), - ('credential_id', models.CharField(max_length=255, unique=True, verbose_name='Credential ID')), - ('token', models.CharField(max_length=255, verbose_name='Token')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/authentication/migrations/0023_auto_20231010_1101.py b/apps/authentication/migrations/0023_auto_20231010_1101.py deleted file mode 100644 index 81920dfd7..000000000 --- a/apps/authentication/migrations/0023_auto_20231010_1101.py +++ /dev/null @@ -1,57 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-10 02:47 - -import uuid -import authentication.models.access_key -from django.db import migrations, models - - -def migrate_access_key_secret(apps, schema_editor): - access_key_model = apps.get_model('authentication', 'AccessKey') - db_alias = schema_editor.connection.alias - - batch_size = 100 - count = 0 - - while True: - access_keys = access_key_model.objects.using(db_alias).all()[count:count + batch_size] - if not access_keys: - break - - count += len(access_keys) - access_keys_updated = [] - for access_key in access_keys: - s = access_key.secret - if len(s) != 32 or not s.islower(): - continue - try: - access_key.secret = '%s-%s-%s-%s-%s' % (s[:8], s[8:12], s[12:16], s[16:20], s[20:]) - access_keys_updated.append(access_key) - except (ValueError, IndexError): - pass - access_key_model.objects.bulk_update(access_keys_updated, fields=['secret']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0022_passkey'), - ] - - operations = [ - migrations.AddField( - model_name='accesskey', - name='date_last_used', - field=models.DateTimeField(blank=True, null=True, verbose_name='Date last used'), - ), - migrations.AddField( - model_name='privatetoken', - name='date_last_used', - field=models.DateTimeField(blank=True, null=True, verbose_name='Date last used'), - ), - migrations.AlterField( - model_name='accesskey', - name='secret', - field=models.CharField(default=authentication.models.access_key.default_secret, max_length=36, verbose_name='AccessKeySecret'), - ), - migrations.RunPython(migrate_access_key_secret), - ] diff --git a/apps/authentication/migrations/0024_accesskey_ip_group.py b/apps/authentication/migrations/0024_accesskey_ip_group.py deleted file mode 100644 index e34d81751..000000000 --- a/apps/authentication/migrations/0024_accesskey_ip_group.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-31 05:37 - -import authentication.models.access_key -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0023_auto_20231010_1101'), - ] - - operations = [ - migrations.AddField( - model_name='accesskey', - name='ip_group', - field=models.JSONField(default=authentication.models.access_key.default_ip_group, verbose_name='IP group'), - ), - ] diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index 721a189d7..99526e156 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -319,7 +319,7 @@ class AuthPostCheckMixin: @classmethod def _check_passwd_is_too_simple(cls, user: User, password): - if user.is_superuser and password == 'admin': + if password == 'admin' or password == 'ChangeMe': message = _('Your password is too simple, please change it for security') url = cls.generate_reset_password_url_with_flash_msg(user, message=message) raise errors.PasswordTooSimple(url) @@ -353,7 +353,7 @@ class AuthACLMixin: return if acl.is_action(LoginACL.ActionChoices.reject): - raise errors.LoginACLIPAndTimePeriodNotAllowed(user.username, request=self.request) + raise errors.LoginACLNotAllowed(user.username, request=self.request) if acl.is_action(acl.ActionChoices.review): self.request.session['auth_confirm_required'] = '1' diff --git a/apps/authentication/signal_handlers.py b/apps/authentication/signal_handlers.py index c74c3c7ed..9ba927075 100644 --- a/apps/authentication/signal_handlers.py +++ b/apps/authentication/signal_handlers.py @@ -36,6 +36,10 @@ def on_user_auth_login_success(sender, user, request, **kwargs): UserSession.objects.filter(key=session_key).delete() cache.set(lock_key, request.session.session_key, None) + lang = request.COOKIES.get('django_language') + if lang: + user.lang = lang + @receiver(cas_user_authenticated) def on_cas_user_login_success(sender, request, user, **kwargs): diff --git a/apps/authentication/templates/authentication/_msg_different_city.html b/apps/authentication/templates/authentication/_msg_different_city.html index 02dbf4271..b3ca09432 100644 --- a/apps/authentication/templates/authentication/_msg_different_city.html +++ b/apps/authentication/templates/authentication/_msg_different_city.html @@ -7,7 +7,7 @@

{% trans 'Username' %}: {{ username }}
- {% trans 'Login time' %}: {{ time }}
+ {% trans 'Login Date' %}: {{ time }}
{% trans 'Login city' %}: {{ city }}({{ ip }})

diff --git a/apps/authentication/templates/authentication/_msg_rest_password_success.html b/apps/authentication/templates/authentication/_msg_rest_password_success.html index dce3ee13c..8f875a819 100644 --- a/apps/authentication/templates/authentication/_msg_rest_password_success.html +++ b/apps/authentication/templates/authentication/_msg_rest_password_success.html @@ -1,15 +1,15 @@ {% load i18n %} -

{% trans 'Hello' %} {{ name }},

+

{% trans 'Dear' %} {{ name }},

{% trans 'Your password has just been successfully updated' %}

- {% trans 'IP' %}: {{ ip_address }}
+ {% trans 'IP' %}: {{ ip_address }}
{% trans 'Browser' %}: {{ browser }}

-

- {% trans 'If the password update was not initiated by you, your account may have security issues' %}
+ {% trans 'If the password update was not initiated by you, your account may have security issues' %}
{% trans 'If you have any questions, you can contact the administrator' %}

diff --git a/apps/authentication/templates/authentication/_msg_rest_public_key_success.html b/apps/authentication/templates/authentication/_msg_rest_public_key_success.html index c8e8fabb6..327f75cb0 100644 --- a/apps/authentication/templates/authentication/_msg_rest_public_key_success.html +++ b/apps/authentication/templates/authentication/_msg_rest_public_key_success.html @@ -1,15 +1,15 @@ {% load i18n %} -

{% trans 'Hello' %} {{ name }},

+

{% trans 'Dear' %} {{ name }},

{% trans 'Your public key has just been successfully updated' %}

- {% trans 'IP' %}: {{ ip_address }}
+ {% trans 'IP' %}: {{ ip_address }}
{% trans 'Browser' %}: {{ browser }}

-

- {% trans 'If the public key update was not initiated by you, your account may have security issues' %}
+ {% trans 'If the public key update was not initiated by you, your account may have security issues' %}
{% trans 'If you have any questions, you can contact the administrator' %}

diff --git a/apps/authentication/templates/authentication/login.html b/apps/authentication/templates/authentication/login.html index ed70b30f7..fac9974ce 100644 --- a/apps/authentication/templates/authentication/login.html +++ b/apps/authentication/templates/authentication/login.html @@ -215,13 +215,7 @@ } .auto-login input[type=checkbox] { - position: relative; - display: inline-block; - margin-top: 0; - vertical-align: middle; - width: 13px; - height: 13px; - cursor: pointer; + } .error-info { @@ -297,8 +291,7 @@