Skip to content

Releases: MR-TABATA/SyncVey

SyncVey v0.9.1

Choose a tag to compare

@MR-TABATA MR-TABATA released this 23 Oct 12:24

Internal code health, security hardening, and branding consistency updates.

  • TOTP application issuer name: Updated the 2FA authenticator issuer name from legacy Cloud Asset Manager to SyncVey (views.py).
  • Membership role update authorization: Hardened membership_update_view to enforce organization scope lookup, returning 404 rather than 403 on cross-organization member IDs to prevent ID existence discovery.
  • Vulnerability scan loop variable binding: Explicitly bound loop variables (eco, name, version) in vulnerability record builder lambda to prevent potential closure rebinding issues (vulns.py).
  • Cleaned up imports and dead code: Removed unused imports across views.py, apps.py, repo_import.py, and scheduler.py, and dropped unused topology local variable others.

v0.9.0 — ライブラリがGitHubのリポジトリに毎日自動で追従し、既知の脆弱性がElastiCacheにも届く

Choose a tag to compare

@MR-TABATA MR-TABATA released this 13 Oct 06:37

The libraries a system uses now follow its GitHub repository on their own, every day — nothing to upload by hand — and known vulnerabilities cover ElastiCache engines too. This release adds migration 0022 (applied by migrate, as in the setup steps).

Added

  • Lockfiles now follow the application's GitHub repository, every day.
    A lockfile uploaded by hand is stale by tomorrow — the opposite of why
    SyncVey exists — so the way in is now a repository. Under an environment,
    Register and import takes a repository URL (or /tree/<branch>/<folder>
    for a monorepo, e.g. a different branch per environment) and reads the
    lockfiles at the top level — requirements.txt, package-lock.json,
    composer.lock, Gemfile.lock, go.mod — through GitHub's API. From then
    on a daily job (03:30; manage.py refresh_repos --force; off with
    REPO_REFRESH_ENABLED=false) re-imports them, so the library list and its
    vulnerabilities follow the repository without anyone touching it. The screen
    shows the last sync; a failed sync is shown as such and the last good list is
    kept. Nothing is called until a repository is registered, and only
    api.github.com is ever called: the URL is split into owner / repository /
    folder and never fetched as typed. Private repositories need a read-only
    token in SYNCVEY_GITHUB_TOKEN (read from the environment, never stored or
    logged). Importing one file by hand remains as a folded-away fallback and says
    it goes stale. Adds migration 0022.
  • Known vulnerabilities for ElastiCache Redis and Memcached. The same
    VULN_REFRESH_ENABLED=true job now looks ElastiCache engine versions up in
    NVD, with the same badge, CVE list and "AWS may have already fixed some of
    these" note as RDS. Only versions that carry a patch number (5.0.6,
    1.6.6) are checked: ElastiCache updates 7.1-style versions behind the
    scenes, so matching those would report CVEs that are already fixed.
    Valkey isn't in NVD and is skipped.

Changed

  • Importing a lockfile is now one button. The browser's own file control
    ("Choose File / No file chosen", plus a tooltip) is gone: press Import
    lockfile
    , pick a file, and it is imported right away — no second click, and
    nothing left half-done after choosing. The hint under it says so.
  • The resource list and detail no longer say "EKS supports Kubernetes 1.34
    and later".
    A past or nearing end-of-life version now shows just the
    fact — the version, the stages and the dates. Whether to update is left to
    you.
  • CVE descriptions from NVD are shown as the first sentence (or cut at a
    word with "…"), instead of a 300-character cut that could end mid-word.

Full changelog: v0.8.0...v0.9.0

v0.8.0 — サポート切れをAWS自身の日付で判定し、既知の脆弱性を台帳に並べる

Choose a tag to compare

@MR-TABATA MR-TABATA released this 13 Oct 05:14

End-of-life is now judged on AWS's own support schedule, known vulnerabilities appear next to it — for your libraries (from lockfiles) and for RDS engines — and the dashboard's EOL card links to what it counted. This release adds migration 0021 (applied by migrate, as in the setup steps).

Added

  • Known vulnerabilities for your libraries. On Applications & Middleware,
    each environment can Import lockfile (requirements.txt,
    package-lock.json, composer.lock, Gemfile.lock, go.mod): the file is
    parsed in memory, the libraries are recorded, and the file is discarded.
    With VULN_REFRESH_ENABLED=true (off by default) a daily job — or
    manage.py refresh_vulns --force — looks them up on OSV.dev and flags those
    also in CISA's Known Exploited Vulnerabilities catalog. Each vulnerable
    library lists its advisories with severity, fixed versions and a link; the
    summary shows how many are high/critical or known exploited. Only
    (ecosystem, package, version) is sent. Hand-entered libraries are not
    checked, and an OSV outage keeps the previous result rather than showing
    "no vulnerabilities". Dependencies are now unique per version, so two
    copies of one package (nested node_modules) are both kept.
  • Known vulnerabilities for RDS PostgreSQL and MySQL engines. The same
    VULN_REFRESH_ENABLED=true job looks each engine version up in NVD (only the
    product and version are sent; an optional NVD_API_KEY lifts NVD's rate
    limit, otherwise it takes about 7 seconds per version). An instance shows a
    badge in the resource list and a collapsible CVE list in its detail panel,
    with severity, a link to NVD and a "known exploited" mark. The result is for
    the upstream version, and the panel says AWS may already have fixed some of
    it inside RDS. Aurora is skipped, since its versions don't match upstream.
    The OSV and NVD lookups are independent: one being down keeps the other's
    results and the previous records.
  • More plugin seams, so a separately distributed plugin app can add a
    sign-in option or routes without the core importing it:
    extra apps can be
    installed with SYNCVEY_EXTRA_APPS, and an AppConfig can contribute
    login_buttons(request) (shown on the sign-in page) and urls_module.

Changed

  • RDS, Lambda and EKS are now judged against AWS's own support schedule,
    in stages, once EOL data has been fetched
    (EOL_REFRESH_ENABLED=true).
    What matters operationally is the day AWS stops supporting a version, not
    the upstream project's. An RDS PostgreSQL/MySQL version or EKS cluster
    past standard support is shown as extended support (paid) and counted
    as nearing end-of-life; it is past end-of-life only once extended
    support ends too. A Lambda runtime past its deprecation date is shown as
    deprecated, and past end-of-life once AWS blocks updates. The
    asset's detail panel lists both dates and names its basis. Aurora keeps
    the upstream approximation (it has its own schedule), as does anything
    not covered by the fetched data, and offline installs behave as before.
    For extended support the panel says it carries an additional charge and
    links to AWS's pricing page (amounts change, so none are shown); for a
    deprecated Lambda runtime it links to AWS's runtime support policy.

Fixed

  • The dashboard's end-of-life card now links to what it counted. Since
    0.7.0 it counts RDS / Lambda / EKS resources as well as declared
    dependencies, but "Review runtimes" always opened the (often empty)
    applications screen. It now offers "Review resources (N)" — the asset list
    filtered to resources past or nearing end-of-life (?eol=1, with a banner
    and a way back) — and "Review dependencies (N)", each shown only when it
    has something to open.

Full changelog: v0.7.0...v0.8.0

v0.7.0 — EOL判定が、RDS・Lambda・EKSの資源そのものにも掛かる

Choose a tag to compare

@MR-TABATA MR-TABATA released this 08 Oct 05:08

One-stop AWS asset ledger with Terraform drift detection — self-hosted, no SaaS fees.

EOL判定が、宣言された依存だけでなく、資源そのものにも掛かるようになった

これまでEOLを見ていたのは、アプリが宣言した依存(ミドルウェア)だけでした。今回から、RDSのエンジンとバージョン(PostgreSQL / MySQL、Auroraを含む)、Lambdaのランタイム(Python / Node.js / Ruby / Java)、EKSのKubernetesバージョンも、同じEOLデータで判定します。EOLを過ぎた・近い資源は、ダッシュボードのEOLカードの件数と、資産一覧のバッジに出ます。バッジは、サービス名の隣ではなく、そのバージョンを表示している行に付きます(サービス自体が廃止されたように読めないように)。消えた資源(missing_since)は数えません。

AuroraとLambdaは、上流のエンジン・言語のEOL日で判定します。AWS自身の非推奨日とは近いものの同じではありません。EKSには組み込みの日付が無く、EOLデータを取得したあと(EOL_REFRESH_ENABLED=true)にだけ判定されます。

manage.py syncvey export で台帳をJSON / CSVに書き出せる

--format・--system・--env・--output FILE を取ります。消えた資源も含め(missing_since つき)、EOLの判定も一緒に出します。JSONは各資産の保存済み属性も持ちます(--no-raw で省略)。

issueフォーム(バグ報告・機能要望)とPRテンプレート

セキュリティの報告は、非公開のadvisoryフォームへ案内します。

直したもの

  • 資産一覧にRDSのエンジンが出ていなかった — インスタンスクラスだけ出て、postgres 16.2 が db.t3.micro の陰に隠れていました。両方出します。
  • 資産詳細の窓に、属性が1つも出ていなかった — 名前・リージョン・時刻だけでした。保存済みの属性(raw_data。内部用と空のキーは除く)を一覧し、RDS / Lambda / EKSには、サポート終了日つきのEOLの欄を出します。
  • 資産カードの高さがばらばらだった — 一番高いカードに揃えます。
  • 詳細の窓のアイコンが壊れ、プロバイダと種別のピルが空だった — 一覧と同じアイコンの引き方に揃え、プロバイダと種別を表示します。
  • 暗号化されたOpenTofuのstateを上げると「0 asset(s) registered」で終わっていた — 成功した空のインポートに見えていました。復号してから上げるよう伝えて、拒否します。
  • CIが、プラグインのテスト56件を1件も実行していなかった — syncvey_cli と syncvey_drift_risk のテストは tests.py にあり、pytest.ini が拾っていませんでした。拾うようにしました。

確認したこと

OpenTofuのstate(プロバイダ registry.opentofu.org/...)は、Terraformのstateと同じように取り込めます。ただし確認は、OpenTofuの文書にある形のstateで行ったもので、実際の tofu の出力ではありません。

詳細は CHANGELOG。

v0.6.0 — 権限が足りず、4本のスキャナが静かに落ちていた

Choose a tag to compare

@MR-TABATA MR-TABATA released this 16 Sep 00:39

One-stop AWS asset ledger with Terraform drift detection — self-hosted, no SaaS fees.

配布ポリシーの権限が4つ足りず、EBS/EFS/SNS/SQSが静かに欠けていた

aws-setup.md のとおりロールを作ると、18本あるスキャナのうち4本(EBS・EFS・SNS・SQS)が権限エラーで動きませんでした。原因は配布している iam/iam-policy.json に ec2:DescribeVolumes / elasticfilesystem:DescribeFileSystems / sns:ListTopics / sqs:ListQueues が入っていなかったこと。しかもSyncVeyは「失敗したスキャナは報告して続行する」作りなので、エラーにはならず、ただ台帳から4種類のリソースが消えるだけでした。

2026-09-07に実機のAWSアカウントで確認して直しました。4つの権限(sqs:GetQueueAttributes も併せて)を追加しています。既存の環境は iam/iam-policy.json を当て直してください。

ダッシュボードのカードを1つの骨組みに揃えた

Drift / EOL / Freshness の3枚が、今までは「異常時」「平常時」で別々のHTMLブロックでした。同じ骨組み(ラベル→数値→補足→動線)に統合し、平常時も文章ではなく 0 を出すようにしています。ドリフト推移グラフも単色の棒から、変更/追加/削除の内訳表示に変わりました。

htmxの断片URLを直接開いても崩れなくなった

リロードやブックマークでhtmx専用の断片URLを直接開くと、Tailwindを読み込む<head>が無いのでCSSが一切当たらない画面になっていました。ブラウザの直接遷移だけを見分けて、ダッシュボードの外枠に包み直すミドルウェアを追加しています。

詳細は CHANGELOG。

v0.5.0 — 時刻が、どこのものか分かる

Choose a tag to compare

@MR-TABATA MR-TABATA released this 04 Sep 12:56

One-stop AWS asset ledger with Terraform drift detection — self-hosted, no SaaS fees.

時刻が、どのタイムゾーンのものか分かるようになりました

東京で 09:10 に取ったドリフトのスナップショットが、画面では 2026-09-04 00:10 と出ていました。瞬間としては正しいのですが、間違っているように見える形です。TIME_ZONE が UTC 固定で、しかも画面のどこにも UTC と書いていませんでした。

ドリフト検知は「いつ変わったか」が本体です。この時刻を AWS のコンソールや CloudTrail と突き合わせる場面がある以上、ラベルの無い 9 時間は、そのまま読み違いになります。

TZ 未設定      2026-09-04 00:10 UTC
TZ=Asia/Tokyo  2026-09-04 09:10 JST

docker compose がホストの TZ を渡すので、TZ=Asia/Tokyo docker compose up で自分の時刻になります。渡さなければ UTC のままです ── 決め打ちより、曖昧でないほうがいいので。

時刻まで出しているところは、すべてタイムゾーンを併記します。 資産の作成・更新、ドリフトのスナップショットと履歴、消えたリソースの検出時刻。

保存されている値は触っていません。 中身は今までどおり UTC です。変わったのは表示だけで、過去のデータもそのまま読めます。

新しく時刻表示を足したときにタイムゾーンを忘れないよう、テンプレートを走査して落とすテストを置きました。日付だけの表示と「3 時間前」のような相対表示は対象外です ── ずれても意味が変わらないので。

導入の手前からアンケートを外しました

docker compose up の前にアンケートを置いていましたが、試す前に答えられることは何もありません。 導入の摩擦を増やすだけだったので外しました。

docker compose pull && docker compose up -d

詳細は CHANGELOG。

v0.4.0 — starting the app is a pull, not a build

Choose a tag to compare

@MR-TABATA MR-TABATA released this 27 Aug 12:45
2b58c8f

Self-hosted AWS asset ledger with Terraform drift detection. No SaaS, no telemetry — your data stays on your own box.

Highlights

🐳 Starting the app is a pull, not a build

docker compose up -d used to run apt and pip on your machine — several minutes before the first screen, on a laptop that has no reason to compile anything.

Compose now points at jiniie/syncvey:latest (amd64 and arm64, published on v* tags), so starting the app is a pull. SYNCVEY_IMAGE in .env pins a version.

Building from source moved to where it belongs — the developer path:

cp docker-compose.override.yml.example docker-compose.override.yml
docker compose up -d       # build: . plus the working-tree mount, with live reload

There is a side effect worth naming: this is the project's first countable install. A git clone is measured by nothing, and release Source code archives are not measured either, so "how many people are running this?" had no answer that could exist.

📖 The development history explains its own gap

The history page says "80 days" but its first two weeks carry no pull requests, and nothing said why. This repository was re-created on 17 June: the work before that survives as commits, while the pull requests went with the old repository. Elapsed days and the weekly chart count from the first commit in git.

That page had also been reachable only from the landing page's own navigation. It now has an entry from the README and from the download page, and the site has a sitemap.xml.

Upgrading from 0.3.0

git pull
docker compose up -d

The first up after this pulls the image instead of building it. If you were relying on build: . — a local patch, a fork — copy the override example above before starting, or your change will not be in the container you get.

Notes

  • Requires PostgreSQL 18.3 (handled by Docker Compose)
  • To try it without an AWS account: docker compose --profile demo up -d then python scripts/seed_localstack.py (see 0.3.0)
  • Outbound connections are limited to AWS unless you opt in to Slack notifications, EOL refresh, or CloudTrail attribution
  • Security problems: please use private vulnerability reporting, not a public issue

Full detail in CHANGELOG.md.

Full changelog: v0.3.0...v0.4.0

v0.3.0 — try it without an AWS account, and a CLI that told the opposite of the truth

Choose a tag to compare

@MR-TABATA MR-TABATA released this 27 Aug 11:06
4302f0e

Self-hosted AWS asset ledger with Terraform drift detection. No SaaS, no telemetry — your data stays on your own box.

Highlights

🧪 Try it without an AWS account

A demo Compose profile starts a local AWS emulator (LocalStack), scripts/seed_localstack.py fills it with fake resources, and the normal scan and drift path runs against it. No account, no credentials, no bill — the fastest way to see what this tool actually does.

Ten of the eighteen scanners work on the emulator's free edition. The other eight report an error per service and the scan carries on, which is exactly the behaviour deleted-resource detection relies on: a scan that aborts on the first failure cannot tell you what disappeared. The image is pinned to localstack/localstack:4 because :latest now requires an auth token and exits without one. README documents what does and does not work, CloudTrail attribution included.

🐳 Published Docker images

v* tags now build jiniie/syncvey for amd64 and arm64 and push it to Docker Hub.

Until now the only install path was a git clone, which nothing counts — release Source code archives are not measured either, so "how many people are running this?" had no answer that could exist. A pull request that touches the Dockerfile builds the image without pushing, so a broken build surfaces on the branch instead of on release day.

🐛 The CLI called a deleted resource an addition

syncvey drift classified assets on raw_data_prev alone — and a resource that disappears from AWS never gets one, so a deletion printed as + added. The exact opposite of what happened, on the command line, while the screen told the truth.

It now branches on missing_since first, the way the drift report and the snapshot writer already did, and an Auto-Scaling-owned disappearance stays churn rather than failing a build. Found by running the scanner against the emulator above.

🧭 One place decides what drift is

That bug was the fourth copy of the same rule. The classification — appeared, disappeared, changed, Auto Scaling churn, and the order those are judged in — was hand-written in the environment badge, the snapshot writer, the drift report and the CLI. Every time the core learned a category, some copies kept the old answer.

The rule now lives in asset_manager/drift.py as classify(), and the four callers ask it and keep only their own output shape. No behaviour change, but a new test asserts all four report identical numbers for the same environment — so a fifth copy is a failing build rather than a bug report.

Upgrading from 0.2.0

No migration is required beyond the usual:

git pull
docker compose up -d --build

To try the emulator instead of a real account:

docker compose --profile demo up -d
python scripts/seed_localstack.py

Notes

  • Requires Python 3.12 and PostgreSQL 18.3 (both handled by Docker Compose)
  • scripts/metrics.py report prints Docker pulls, release asset downloads and GitHub traffic in one place, and says which figures do not exist yet rather than printing a confident zero. A scheduled job stores the traffic numbers daily, because GitHub keeps only the last 14 days and a day not collected is gone for good
  • Outbound connections are limited to AWS unless you opt in to Slack notifications, EOL refresh, or CloudTrail attribution
  • Security problems: please use private vulnerability reporting, not a public issue

Full detail in CHANGELOG.md.

Full changelog: v0.2.0...v0.3.0

v0.2.0

Choose a tag to compare

@MR-TABATA MR-TABATA released this 20 Aug 11:45
cde3045

Self-hosted AWS asset ledger with Terraform drift detection. No SaaS, no telemetry — your data stays on your own box.

Highlights

🕸️ Blast radius — how far a drift reaches

One drifted resource is rarely alone; other resources point at it. SyncVey now walks the reference graph outward from each drift and ranks everything it can reach by severity-weighted, distance-decayed impact, so you fix the change that touches the most, first.

The dependency graph is recovered from the attribute values already being scanned, and is scoped per environment — identical IDs in different environments never wire together. A stateless plan structurally can't do this; it needs the live graph.

Detachable like the other plugins: remove the app and the feature disappears.

🐛 Deleted resources were missing from the drift totals

The removed category shipped in 0.1.0, but two places built the drift total by hand and were never updated:

  • the dashboard hero band reported "no drift detected" for an environment where resources had actually been deleted
  • the weekly Slack briefing under-counted both the total and the week-over-week trend

Both features exist specifically to make deletions noticeable, so silently dropping them was the worst possible failure. Fixed, with regression tests that fail if the fix is removed.

🌐 Both halves of the translation problem are now gated in CI

gettext fails silently in two different directions, and this project has been bitten by both:

Failure Gate
A translation exists but was never reviewed (#, fuzzy, or empty) — renders as English, or ships visibly wrong asset_manager.i18n_check
A string was never extracted into the catalogue at all — nothing flags it, and it renders as English scripts/check_i18n_extraction.py

Both of this repo's translation holes — 50 strings, then 15 more — were found by a human noticing English text on a Japanese screen. That is the worst way to find them. Now they fail on the branch that introduces them.

The 65 strings themselves are also translated in this release. One of them is a good illustration of why the fuzzy gate matters: Auto Scaling had been machine-guessed as 自動スキャン ("Auto Scan").

Upgrading from 0.1.0

No migration is required beyond the usual:

git pull
docker compose up -d --build

The new blast-radius plugin is enabled by default and stores nothing — it computes from assets you already have. To leave it out, remove syncvey_blast_radius.apps.BlastRadiusConfig from INSTALLED_APPS; its navigation entry disappears and its route 404s.

Notes

  • Requires Python 3.12 and PostgreSQL 18.3 (both handled by Docker Compose)
  • Outbound connections are limited to AWS unless you opt in to Slack notifications, EOL refresh, or CloudTrail attribution
  • Security problems: please use private vulnerability reporting, not a public issue

Full detail in CHANGELOG.md.

Full changelog: v0.1.0...v0.2.0

v0.1.0

Choose a tag to compare

@MR-TABATA MR-TABATA released this 19 Aug 10:38
36f3fdb

Self-hosted AWS asset ledger with Terraform drift detection. No SaaS, no telemetry — your data stays on your own box.

This is the first tagged release. SyncVey has been usable for a while; this marks the point where the surface is stable enough to pin a version to.

What it does

Ledger — discovers 17+ AWS resource types (EC2, ECS, Lambda, RDS, DynamoDB, ElastiCache, EFS, EKS, S3, ALB, VPC, EBS, SNS, SQS, API Gateway, CloudFront, Route 53, Secrets Manager) via boto3, cross-account through AssumeRole, read-only by design.

Drift — attribute-level diff between your tfstate and live AWS, with history and a trend chart. Beyond the basics:

  • It catches what Terraform can't see. Resources created by hand in the console show up too, not just changes to what's already in state.
  • It notices deletions. A resource that vanishes from AWS is reported as removed drift instead of quietly sitting in the ledger forever. Marking is confined to the regions and resource types that scanned cleanly, so a throttled API call can never be mistaken for a mass deletion.
  • It doesn't cry wolf on Auto Scaling. Instances an ASG launches or terminates are churn, not drift — read from a tag already being scanned, with no extra API call or IAM permission.
  • It grades drift by risk and traces who made the change via CloudTrail.
  • It flags rotation that should have happened but didn't — a standing-state check on Secrets Manager, not a diff.

Beyond drift — application/dependency tracking, EOL alerts for end-of-life runtimes (offline by default), architecture diagrams, and a syncvey CLI that fails your build on drift (--exit-code).

Platform — multi-tenant, TOTP 2FA, audit log, Japanese and English UI, Docker Compose deployment. Optional features are detachable plugins: remove the app and its navigation and routes disappear.

Getting started

git clone https://github.com/MR-TABATA/SyncVey.git
cd SyncVey
cp .env.example .env    # edit SECRET_KEY and DB settings
docker compose up -d

Then open http://localhost:8000. See the README for AWS setup, and try the built-in sample tfstate files if you'd rather look around before pointing it at a real account.

Notes

  • Requires Python 3.12 and PostgreSQL 18.3 (both handled by Docker Compose)
  • Outbound connections are limited to AWS unless you opt in to Slack notifications, EOL refresh, or CloudTrail attribution — all documented in the README
  • Found a security problem? Please use private vulnerability reporting, not a public issue. See SECURITY.md.

Full detail in CHANGELOG.md.