hashicorp

Stars and mentions

Last 30 days, Oct 5 – Nov 3

GitHub stars376
mentions62
010203040Oct 5Oct 19Nov 3
UTC days · repositories hashicorp owns21 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-20

npm9.1M
02.3M4.6M6.8M9.1MOct 5Oct 19Nov 3
Oct 26npm: 2/12 packages observed

Across 12 known packages in repositories hashicorp owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete.

Top repositories

hashicorp’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside hashicorp’s account where hashicorp opened or reviewed pull requests in the past 365 days.

Who noticed hashicorp

Everyone who starred or forked hashicorp’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

62posts
Nov 40 posts
  1. OpenTofu or Terraform: What to Pick for Existing Code Originally published on kuryzhev.cloud --- <p>The question of OpenTofu or Terraform tends to arrive on a quiet Tuesday. A repo with 200 resources, a remote state in S3 and a CI pipeline pinned to <code>terraform</code> works fine, until someone asks whether the next upgrade should be to the other tool. Nothing is broken, so the real question is whether switching buys anything that justifies the risk.</p> <p>The timing is worth noting. Both projects shipped new minor cycles recently: OpenTofu 1.13 (latest patch 1.13.5, cycle released 2026-09-30, <a href="github.com/opentofu/opentofu/releases">release notes</a>) and Terraform 1.17 (latest patch 1.17.1, cycle released 2026-10-21, <a href="github.com/hashicorp/terraform/releases">release notes</a>). Anyone planning a quarterly upgrade has two fresh targets. The two projects follow independent roadmaps, so check each changelog for features that exist in only one of them.</p> <p><strong>Short answer:</strong> if your code is plain AWS/GCP/Azure/Kubernetes resources and you have no contract with HCP Terraform, you can usually stay on Terraform 1.17 or move to OpenTofu 1.13 at low risk, so choose based on licensing and features. If you depend on HCP Terraform, Stacks or other HashiCorp-hosted services, stay on Terraform. If you want client-side state encryption or an open-governance licence, trial OpenTofu with the dry-run below before committing.</p> <h2>When the OpenTofu or Terraform choice actually matters</h2> <p class="devops-inline-image"></p> <p>For a small repo with a single backend, the choice is mostly cosmetic. It starts to matter in four situations:</p> <ul> <li><strong>Licensing review.</strong> Terraform releases after 1.5.x use the Business Source License; OpenTofu is MPL-2.0 under the Linux Foundation. Legal teams sometimes care, particularly if you ship tooling to customers. Read the current licence text yourself rather than relying on a blog summary.</li> <li><strong>State sensitivity.</strong> State holds secrets in plain text unless the backend encrypts it. OpenTofu has built-in state and plan encryption. Terraform relies on backend encryption and on its ephemeral and write-only mechanisms to keep values out of state. Check the Terraform docs for what your version supports.</li> <li><strong>Platform coupling.</strong> If your org runs workspaces, policies and run tasks in HCP Terraform or Terraform Enterprise, the tool and the platform are one decision.</li> <li><strong>Feature divergence.</strong> Since the 2023 fork the two projects have added different features and, in some cases, different syntax for similar ideas. Config that uses a tool-specific feature will not run on the other.</li> </ul> <p>Neither tool has a blanket advantage. Compare the changelogs for your specific version jump, not for the headline releases.</p> <h2>Option A: OpenTofu 1.13</h2> <p><strong>Pros</strong></p> <ul> <li>Open governance and an MPL-2.0 licence, which simplifies procurement and redistribution questions.</li> <li>Native state and plan encryption with pluggable key providers (including AWS KMS), configured in the <code>terraform</code> block. This matters when state lands in shared buckets.</li> <li>Features that landed after the fork, such as <code>for_each</code> on providers and the <code>-exclude</code> flag, are documented on <a href="opentofu.org">opentofu.org</a>. Confirm what is in 1.13 against its changelog.</li> <li>Same HCL, same provider protocol, same workflow. The binary is <code>tofu</code> and the commands match, so the CLI is familiar.</li> </ul> <p><strong>Cons</strong></p> <ul> <li>Migration becomes effectively one-way once you encrypt state or adopt OpenTofu-only syntax. Terraform cannot read encrypted state, so going back means decrypting with OpenTofu or reverting the config first.</li> <li>Provider and module sourcing goes through the OpenTofu registry. Your <code>.terraform.lock.hcl</code> entries will change, and any tooling hard-coded to <code>registry.terraform.io</code> needs a check.</li> <li>Third-party integrations (scanners, IDE plugins, CI templates) vary in how well they support <code>tofu</code>. Test yours rather than assuming.</li> <li>Commercial support comes from vendors rather than the original authors, which may or may not matter to your org.</li> </ul> <h2>Option B: Terraform 1.17</h2> <p><strong>Pros</strong></p> <ul> <li>Zero migration. Your pipeline, lock files, runbooks and team habits stay as they are, and upgrades inside the 1.x line follow the documented <a href="developer.hashicorp.com">upgrade guides</a>.</li> <li>First-party integration with HCP Terraform and Terraform Enterprise, including features that exist only there (Stacks, hosted policy and drift tooling). HashiCorp is now part of IBM, so vendor support contracts are a single conversation for many enterprises.</li> <li>Most vendor docs and provider examples still assume <code>terraform</code>, so troubleshooting is easier to search.</li> </ul> <p><strong>Cons</strong></p> <ul> <li>The BSL licence restricts offering a competing product. Most internal use is fine, but verify the terms against your situation, especially if you resell infrastructure automation.</li> <li>No built-in client-side state encryption. You depend on backend-side encryption (for example S3 with KMS) and on keeping secrets out of state in the first place.</li> <li>Roadmap and licence decisions sit with one vendor. That is a trade-off, not a defect, but it is a dependency you should name.</li> </ul> <h2>Decision matrix</h2> <table> <thead><tr><th>Situation</th><th>Lean toward</th><th>Why</th></tr></thead> <tbody> <tr><td>HCP Terraform / Enterprise in daily use</td><td>Terraform 1.17</td><td>Platform features are tied to the vendor CLI</td></tr> <tr><td>Self-managed CI with S3/GCS backend</td><td>Either</td><td>Low switching cost; decide on licence and features</td></tr> <tr><td>Need encrypted state independent of the backend</td><td>OpenTofu 1.13</td><td>Built-in encryption block</td></tr> <tr><td>Legal requires an OSI-approved licence</td><td>OpenTofu 1.13</td><td>MPL-2.0</td></tr> <tr><td>Heavy use of vendor-supported Terraform tooling</td><td>Terraform 1.17</td><td>Fewer integration surprises</td></tr> <tr><td>Config written for a much older Terraform (1.5.x or earlier)</td><td>Upgrade first, decide later</td><td>Big version jumps are the risk, not the tool</td></tr> <tr><td>Small team, no pain today</td><td>Stay put</td><td>Switching has a cost and no immediate payoff</td></tr> </tbody> </table> <p><strong>Watch out:</strong> do not combine a tool switch with a major provider upgrade in one change. When a plan shows unexpected diffs, you want exactly one variable to blame.</p> <h2>Evidence-based recommendation</h2> <p>The evidence for an urgent move in either direction is thin. Both tools plan and apply the same core HCL against the same providers. The differences that matter are licence, state handling, and platform lock-in, and you can evaluate those without touching production.</p> <p>So the practical approach is a read-only trial. The following runs OpenTofu against a copy of your current setup. It takes a state backup first, then produces a plan and never applies. Run it from a branch.</p> <pre><code class="language-bash"># 1. Back up current state with the tool you use today terraform state pull &gt; ../backup-$(date +%F).tfstate 2. Check versions; OpenTofu evaluates required_version against its own version number, so review any terraform { required_version } constraint terraform version tofu version 3. Re-init with OpenTofu (rewrites .terraform.lock.hcl; review the diff) rm -rf .terraform tofu init tofu providers lock -platform=linux_amd64 -platform=darwin_arm64 4. Read-only comparison: -lock=false avoids blocking teammates; never apply here tofu plan -lock=false -detailed-exitcode echo "exit code: $?" </code></pre> <p>To verify the result, check the exit code. <code>0</code> means no changes, which is what you want from an unchanged codebase. <code>2</code> means a diff, so read it before you do anything else. <code>1</code> is an error, typically a provider source or backend setting. If the plan is clean, run the same steps in CI on a non-production workspace.</p> <p><strong>Watch out:</strong> run <code>tofu apply</code> only on a workspace you can afford to roll back. A newer tool can write state that the older one refuses to read, and the backup from step 1 is your way out.</p> <p>If the trial is clean and you want OpenTofu's encryption, add it deliberately as a separate change. Existing state is unencrypted, so the first configuration needs an unencrypted fallback to read it. This example uses AWS KMS; the key alias is a placeholder for your own.</p> <pre><code class="language-hcl"># encryption.tf (OpenTofu only; Terraform will reject this block) terraform { encryption { key_provider "aws_kms" "main" { kms_key_id = "alias/tofu-state" # your KMS key alias region = "eu-west-1" key_spec = "AES_256" } method "aes_gcm" "default" { keys = key_provider.aws_kms.main } # Temporary: lets OpenTofu read the existing unencrypted state method "unencrypted" "migrate" {} state { method = method.aes_gcm.default fallback { method = method.unencrypted.migrate } } } } </code></pre> <p>After the next <code>tofu apply</code> writes encrypted state, remove the <code>unencrypted</code> method and the <code>fallback</code> block, and add <code>enforced = true</code> inside <code>state</code> so OpenTofu refuses to write unencrypted state. Verify by reading the raw object from the backend rather than through <code>tofu</code>, which decrypts transparently, for example <code>aws s3 cp s3://&lt;your-state-bucket&gt;/&lt;your-state-key&gt; - | head -c 200</code>. Encrypted state is a JSON envelope with encryption metadata instead of readable resource attributes. Details, plan encryption and rollback options are in the <a href="opentofu.org">OpenTofu documentation</a>, so follow those rather than improvising.</p> <p>The recommendation, with conditions:</p> <ul> <li><strong>Stay on Terraform 1.17</strong> if you use HCP Terraform or Enterprise, or if nothing in the matrix hurts today.</li> <li><strong>Move to OpenTofu 1.13</strong> if licence terms or state encryption are real requirements, and the dry-run above shows a clean plan.</li> <li><strong>Do neither yet</strong> if you are several minor versions behind. Upgrade within your current tool first, then compare.</li> </ul> <p>For related infrastructure patterns, browse more guides on <a href="kuryzhev.cloud">kuryzhev.cloud</a>. Whichever way you go, pin the binary version in CI so the choice stays a decision and never becomes drift.</p> <h2>Related</h2> <ul> <li><a href="kuryzhev.cloud">Terraform Vault Secrets: Keep Them Out of State and Git</a></li> <li><a href="kuryzhev.cloud">Terraform Modules for AWS VPC, IAM, and S3: Structure That Scales</a></li> <li><a href="kuryzhev.cloud">Why an LLM reviewer misses risky Terraform plan changes</a></li> </ul>

  2. aws login + assumeRole + terraform のエラー回避 問題の概要 条件 aws login を使って認証する。 そこからさらに assumeRole して別ロールを使う その状態で terraform を実行する 発生する現状: 以下のエラーが発生する ╷ │ Error: failed to load assume role arn:aws:iam::123456789012:role/MY-ROLE, of profile LOGIN-PROFILE, <nil> │ │ ╵ つまり、aws login と assumeRole を併用して terraform を使えない。 対処方法 ! 本対処は aws-sdk-go-v2 の現時点の実装を利用したワークアラウンドであり、正しい設定ではなく今後の aws-sdk-go-v2 の更新で使えなくなる可能性があります。 以下のように assumeRole 用のプロファイルを作成する: aws-sdk-go-v2 で aws login + assumeRole が失敗する問題回避用のプロファイル [profile ROLE-PROFILE-go] login_session = arn:aws:iam::123456789012:user/MY-USER region = ap-northeast-1 role_arn = arn:aws:iam::123456789012:role/MY-ROLE role_session_name = MY-USER 通常の aws login + assumeRole 用のプロファイル (参考) [profile ROLE-PROFILE] region = ap-northeast-1 role_arn = arn:aws:iam::123456789012:role/MY-ROLE role_session_name = MY-USER source_profile = LOGIN-PROFILE aws login で作成されるプロファイル [profile LOGIN-PROFILE] login_session = arn:aws:iam::123456789012:user/MY-USER region = ap-northeast-1 terraform 利用時にはこの ROLE-PROFILE-go を使う: AWS_PROFILE=ROLE-PROFILE-go terraform init 事象の詳細 再現手順 前提条件 コンソールログイン用のユーザーもしくはロールがある (IAM ユーザー MY-USER とする) そこから assumeRole して使うユーザーがある (IAM ロール MY-ROLE とする) MY-USER でコンソールログインする。 以下コマンドで awscli の認証を行う。 aws login --profile LOGIN-PROFILE ~/.aws/config に以下のようなエントリーが作成される: [profile LOGIN-PROFILE] login_session = arn:aws:iam::123456789012:user/MY-USER region = ap-northeast-1 ~/.aws/config に以下のようなエントリーを作成する: [profile ROLE-PROFILE] region = ap-northeast-1 role_arn = arn:aws:iam::123456789012:role/MY-ROLE role_session_name = MY-USER source_profile = LOGIN-PROFILE awscli でこのプロファイルで MY-ROLE として認証できることを確認する。 AWS_PROFILE=ROLE-PROFILE aws sts get-caller-identity aws へのアクセスが発生する Terraform テンプレートで terraform を実行する。バックエンドに S3 バケットを使用するなど。 AWS_PROFILE=ROLE-PROFILE terraform init バックエンドに S3 を使用しておらず AWS プロバイダーで AWS リソースにアクセスしている場合は init ではエラーにならず plan などでエラーになる。 以下のようなエラーが発生する。 ╷ │ Error: failed to load assume role arn:aws:iam::123456789012:role/MY-ROLE, of profile LOGIN-PROFILE, <nil> │ │ ╵ 原因 aws-sdk-go-v2 のバグによる問題です。 このため実際は terraform 固有の事象ではなく、 aws-sdk-go-v2 を使う golang アプリケーション共通の事象です。aws-sdk-go-v2 は AWS 公式のライブラリーのため、事実上、 golang 実装の AWS を扱うアプリケーションはすべて同じ問題に遭遇すると考えてよいでしょう。 正確にはバグなのか仕様なのかは不明です。本事象は 2026 年 6 月に Login session (aws login) credentials rejected when used as source_profile for an assume-role profile #3446 で報告されており、#3447 で修正案のプルリクエストも提出されているのですが、2026 年 11 月現在もマージされていません。 原因は github.com/aws/aws-sdk-go-v2/config のプロファイルが認証情報を作成できるか判定する処理 で、 「login_session があるときは認証情報を作成する」という判定がないことによるものです。 その結果、source_profile に login_session (aws login 由来) によって認証するプロファイルを指定すると、認証情報が生成できないとして「failed to load assume role (元のプロファイルで role_arn に指定しているプロファイル), of profile (source_profile に指定したプロファイル), (エラー情報。error が生成されていないので常に nil)」というエラーになります。 回避方法 ワークアラウンドプロファイルによる回避 aws-sdk-go-v2 の実装上、同一プロファイル内に login_session と role_arn の両方を書くと login_session (aws login 由来) を使って認証情報を解決した後、 assumeRole する動作をします。 golang アプリケーション (aws-sdk-go-v2) 用の設定 login_session を書いて aws login の認証情報を使った後、 role_arn で assumeRole で認証情報を作成する [profile ROLE-PROFILE-go] login_session = arn:aws:iam::123456789012:user/MY-USER region = ap-northeast-1 role_arn = arn:aws:iam::123456789012:role/MY-ROLE role_session_name = MY-USER コード上の該当箇所: login_session があると aws login 由来の認証情報を解決してきて、そのまま認証情報の解決処理を続行する: config/resolve_credentials.go role_arn があるとその時点の認証情報を使って assumeRole を行う: config/resolve_credentials.go なお、このプロファイルは botocore では role_arn があるのに source_profile がないため不適切な設定と判定されるため、 awscli などで使うとエラーになります: github.com/boto/botocore/blob/1.43.123/botocore/c… $ AWS_PROFILE=ROLE-PROFILE-go aws sts get-caller-identity aws: [ERROR]: Partial credentials found in assume-role, missing: source_profile or credential_source 一方、今回のワークアラウンドプロファイルにさらに source_profile を追加すると、aws-sdk-go-v2 側でワークアラウンドが機能するよりも先に今回の問題となっているチェック処理に引っかかるため、元の通りのエラーになってしまいます。 このため、このワークアラウンドプロファイルは golang アプリケーション専用に、awscli 等で使うプロファイルとは別に作っておく必要があります。 switch role してから aws login する AWS コンソール上で「他のロールに切り替える」の操作を行い、 MY-ROLE に切り替えてから aws login することで、直接 MY-ROLE の状態の認証情報を得ることが出来ます。 正規の方法で安全ですが、使用するロールが多い場合は切り替えのたびに aws login が必要なので煩わしいという問題があります。 また、aws login 用のトークン発行を許可するためにロールに SignInLocalDevelopmentAccess ポリシーを割り当てておく必要があります。 参考: コンソール認証情報を使用して AWS ローカル開発にログインする - AWS Command Line Interface Appendix: terraform / opentofu の aws login 対応バージョン terraform や opentofu で aws login を使うためには、一定以上のバージョンである必要があります。 また、S3 バックエンドを使う場合は terraform / opentofu 本体のバージョンが影響し、 AWS 上のリソースの作成については AWS プロバイダー (terraform-aws-provider) のバージョンが影響します。 必要な aws-sdk-v2-go のバージョン github.com/aws/aws-sdk-go-v2/credentials v1.19.0 以上 github.com/aws/aws-sdk-go-v2/config v1.32.0 以上 already reviewed add logincreds provider - #3230 がマージされたバージョンを使う必要がある。 Terraform のバージョン: v1.15.0 以上、または v1.14.9 以上 v1.15.0 での更新: 12276b8 v1.14.9 での更新: c78dd8d OpenTofu のバージョン: v1.12.0 以上、または v1.11.10 以上 v1.12.0 での更新: 5b6ca0a v1.11.10 での更新: 5e94874 AWS プロバイダー (terraform-aws-provider) のバージョン: v6.23.0 以上、または v6.22.1 以上、 v6.23.0 / v6.22.1 での更新: bead7e4 v5 系は現時点の最新の v5.100.0 でもサポートなし

  3. Consul Binding Rules Outlive the Patch !Field Notes — Engineering Notes from the Complexity Gap | Rack2Cloud Consul binding rules generated by the consul-k8s Helm chart can survive the upgrade that was supposed to correct them. HashiCorp published advisory HCSEC-2026-50 (CVE-2026-110720) on October 26. consul-k8s 1.8.18 (October 19) and 2.1.0 (October 23) changed how those rules match Kubernetes ServiceAccounts, and both release notes carry an exception that is easy to read past: rules belonging to components that were disabled before the upgrade are not rewritten. !consul binding rules — chart version upgraded to fixed release while a name-only rule for a disabled component remains What the Advisory Confirms, and What It Doesn't This is an identity trust boundary hosted on Kubernetes, which makes it a platform governance question before it is a patching one. The modern infrastructure and IaC strategy frame applies: the boundary is defined by generated configuration, and generated configuration has a lifecycle separate from the chart version that produced it. Four separate classes of statement are in play, and they carry different weight. | Evidence class | Statement | Source | |---|---|---| | Advisory-confirmed | consul-k8s 0.42.0 up to 2.0.4 is affected; fixed in 1.8.18 and 2.1.0. Applies when global.acls.manageSystemACLs=true. The attacker must be able to create a ServiceAccount and obtain its token in another namespace, and must have network access to the Consul API. | HCSEC-2026-50 | | Release-note-evidenced | Binding rules matched on ServiceAccount name only; they now also require the Consul release namespace. Existing rules are updated on upgrade, except rules for components disabled before the upgrade. Components outside the release namespace must be moved into it. | consul-k8s changelog, 1.8.18 and 2.1.0 | | Inferred | That these release-note changes are the fix for CVE-2026-110720. The changelog does not cite the CVE; the link rests on the matching mechanism, versions and timing. | This post | | Not stated | Severity or CVSS score, exploitation status, any workaround. | Absent from the advisory text as reviewed | Read the table as a boundary on this post. Everything below the inferred row assumes the linkage holds, and nothing below it assigns a severity the advisory did not. What the Consul Binding Rules Matched With ACL management enabled, the chart creates the Consul auth method and the binding rules that map a Kubernetes ServiceAccount to a Consul identity. Before the fix, those Consul binding rules selected on the ServiceAccount name alone. A ServiceAccount carrying the same name in a different namespace satisfied the selector. That is the precondition the advisory describes: create a ServiceAccount and obtain its token in another namespace, then present it to the Consul API. After the fix, a rule requires the name and the Consul release namespace. The name stops being an identity and becomes one half of one. The chart generates these Consul binding rules, so inspecting the current Helm values is not enough to establish what the Consul server will accept. A rule can remain after the component that prompted its creation has been disabled. The rule set can reflect components that were enabled previously, not just components enabled now. The release notes specifically warn that rules for components disabled before the upgrade are not rewritten. What the Upgrade Does Not Rewrite The release notes say existing rules are updated on upgrade. They also state the exception outright: rules for components that were disabled before the upgrade are not rewritten. To correct them, delete the rule manually, or re-enable the component and upgrade again. That exception changes what "upgraded" means. A cluster on 2.1.0 or 1.8.18 where a gateway was disabled last quarter can still hold a name-only rule for that gateway. The chart version is correct. The rule is the pre-fix rule. A version inventory will report the first fact and say nothing about the second. Because both fixed releases shipped before the October 26 advisory, an upgrade record may predate awareness of the vulnerability. In any case, a record that confirms the deployed version does not establish whether the existing binding rules were rewritten. The disabled-component exception makes that distinction operationally important. A second constraint sits next to it: components outside the Consul release namespace must be moved into it. A namespace-aware rule cannot match a component that was never placed in the namespace it now requires, so the placement check precedes any cleanup. Moving a component between namespaces is a change to a live deployment, not a formality; assess the effect on the component and its dependencies first. The general pattern here is owned elsewhere. The architecture of premature closure covers declaring a remediation complete on the strength of a closure signal, and DKM ACL hardening shows the same gap in an ACL cleanup. This post adds only the Consul-specific mechanism: where the stale state lives, and why the upgrade path leaves it. That is a governance and drift condition, a permission whose reason for existing was removed while the permission stayed. !consul binding rules upgrade gap — enabled components rewritten, disabled component rules left unchanged Inspect the Rules the Chart Generated Auditing Consul binding rules means working against the Consul server, not against Helm values. Values describe intent. The rules that exist describe what the API will accept. Exact commands are left out here on purpose: confirm the syntax against the documentation for your Consul version before running anything. The changelog itself shows a binding-rule list and a delete example, which is a pointer, not a substitute for that check. 01 — RECORD THE VERSION AND THE ACL SETTING Note the consul-k8s version actually deployed and whether global.acls.manageSystemACLs is true. The advisory conditions on both, and a cluster outside either condition changes the rest of the work. 02 — LIST THE BINDING RULES THAT ACTUALLY EXIST Pull them from the Consul side. Do not reconstruct them from the chart values, because the values cannot show a rule left behind by a component that is no longer enabled. 03 — CHECK EACH RULE FOR A NAMESPACE CONSTRAINT A rule that selects on ServiceAccount name alone is a pre-fix rule, regardless of which chart version is now running. 04 — IDENTIFY EVERY COMPONENT THAT HAS EVER BEEN DISABLED Use release history, GitOps history or change records. Sync-catalog and the gateway components are the ones the release notes name; treat the list as a starting point, not a boundary. 05 — RESOLVE EACH STALE RULE Follow the documented upgrade path for the deployed release: delete the stale rule manually, or re-enable the component and upgrade again. Before changing a live component or moving it between namespaces, assess the effect on the deployment and its dependencies. 06 — CHECK PLACEMENT BEFORE MOVING ANYTHING Confirm every component that needs a rule sits in the Consul release namespace. Where one does not, plan the move as a change in its own right before relying on a namespace-aware rule. 07 — RECORD THE EVIDENCE Save the rule list before and after, with the version and date. Without that record, the verification is a statement and not a result. > Diagnostic: "Which components in this cluster have ever been disabled, and which of them still carry a binding rule?" If the answer to the question is "we don't know", step 2 is the work. Everything after it depends on a rule list that was read from the server. Architect's Verdict The advisory gives you a version range and a fixed version. It does not give you a clean cluster, because the thing that was wrong lived in generated rules, and generated rules are not versioned with the chart. Treat the chart version and the Consul binding rules as two verification targets. The first is an inventory query. The second requires reading what the Consul server will actually accept, component by component, including the ones nobody runs anymore. The release notes document the exception, and the exception is the part a version-only upgrade ticket may not capture. An identity rule outlives the component it was written for. That is the thing to audit. Additional Resources - Modern Infrastructure & IaC Strategy Guide — pillar hub for platform architecture, state, and automation governance. - Governance & Drift — the learning-path stage on permissions and exceptions that outlive their reason. - The Architecture of Premature Closure — the parent pattern: a closure signal declared as verified state. - DKM ACL Hardening — a recent instance of remediation that missed a path in an ACL cleanup. - HCSEC-2026-50 — Consul cross-namespace authorization bypass; affected and fixed consul-k8s versions. - consul-k8s CHANGELOG — release notes for 1.8.18 and 2.1.0, including the disabled-component exception. --- Originally published at rack2cloud.com

  4. This is, but is still limited by their license: hashicorp/vault

  5. OpenTofu を選ぶ理由はライセンスだけではない: 1.7〜1.12 の機能で変わる構成管理 OpenTofu を選ぶ理由として語られるのはライセンスの話が中心ですが、1.7 以降に入った機能のほうが日々の構成管理には効きます。lifecycle の enabled と動的な prevent_destroy、backend 設定への静的評価、provider の for_each で、環境ごとに root module を複製したり count = var.x ? 1 : 0 を書いたりする必要がなくなります。加えて、state と plan のクライアント側暗号化という防御層があります。いずれも 2026 年 10 月時点の Terraform 1.17 にはない機能です。 この記事では、OpenTofu を採用する理由をライセンスと機能の両面から整理し、最後に「どんな構成なら乗り換える価値があるか」の判断基準を示します。Terraform から OpenTofu への移行を検討している方、すでに OpenTofu を使っているが「ライセンス以外に何が良いのか」を説明しきれていない方向けです。 記事の内容は 2026 年 10 月時点の公式ドキュメントと CHANGELOG に基づきます。OpenTofu は 1.13.2、Terraform は 1.17.1 まで確認しています。手元の環境は OpenTofu v1.13.2 で、1.13 ではこの記事で扱う機能に挙動変更はありません。コード例は AWS を題材にし、環境名を var.env(dev / prod など)で受け取る前提で書いています。 ライセンスとガバナンスの話は前提にすぎない まず前提を確認します。Terraform は 2023 年 8 月に MPL 2.0 から BUSL 1.1 に変わり、HashiCorp は 2025 年に IBM による買収が完了しました。OpenTofu は Terraform からフォークされ、MPL 2.0 で Linux Foundation 配下のプロジェクトとして運営されています。 これは「将来ライセンスが変わっても困らない」という保険の話で、採用理由として間違ってはいません。ただ、これだけだと「Terraform でも実害はない」という反論に答えられません。本当に効くのは次の機能面の差です。 採用理由になる 4 つの機能 いずれも Terraform 1.17(2026 年 10 月時点)にはない機能です。Terraform は版を重ねるごとに差を埋めてきているので(後述の比較表を参照)、「ない」は常に版付きで考えてください。日常的に効く順に並べます。 lifecycle の新しい引数: 条件付きリソースと削除防止を素直に書く(1.11 / 1.12〜) lifecycle ブロックに加わった引数のうち、Terraform にないのは次の 2 つです。 引数 導入版 置き換えるもの enabled = <bool> 1.11 count = var.x ? 1 : 0 動的な prevent_destroy 1.12 環境ごとの module 複製や別定義 同じ 1.12 で入った destroy = false は Terraform 1.16 にも同等の引数があるため、後の章で扱います。 enabled(1.11〜) リソースや module を 0 個か 1 個で出し分けるための引数です。count = var.x ? 1 : 0 と [0] 参照の代わりになります。 resource "aws_instance" "bastion" { ami = var.bastion_ami instance_type = "t3.micro" lifecycle { enabled = var.env == "dev" } } 挙動と制約は次の通りです。 false のときはリソースが設定に存在しないものとして扱われ、参照は null になります。既存の実物があれば count を 0 にしたときと同様に destroy が計画されるので、切り替え時は plan を確認してください count 方式からの移行に state 操作は要りません。aws_instance.bastion[0] は自動で aws_instance.bastion に移されます(moved ブロック不要) 無効化されたリソースの属性を直接参照すると plan / apply が失敗します。try(aws_instance.bastion.id, null) か aws_instance.bastion != null ? ... : ... で守ります count / for_each とは併用できません。値は plan 時に確定している必要があり、sensitive・null・ephemeral な値も使えません 1.11.4 以降、ローカルに provider 設定を持つ module では enabled を使えません。count / for_each / depends_on に元からあった制約と揃えた修正で、設計時の見落としがパッチ版で直されたものです 使いどころは、環境によって作る・作らないが分かれる単発のリソースです。本番だけの監視、dev だけの踏み台などが典型で、[0] が消えて参照側が読みやすくなります。 動的な prevent_destroy(1.12〜) 従来は定数しか書けなかった prevent_destroy が、同じ module 内の変数を参照できるようになりました。 resource "aws_db_instance" "main" { ... lifecycle { prevent_destroy = var.env == "prod" } } 本番だけ削除防止を効かせたい DB やバケットに使います。prevent_destroy のためだけに環境別の定義を持つ必要がなくなります。 注意点として、prevent_destroy は resource ブロックごと消すと一緒に消えるので、ブロック削除による destroy は防げません。それを防ぐのは後述の destroy = false です。 使い分け 目的 使うもの 環境によって作る・作らないを切り替える enabled 本番だけ誤削除を防ぐ(ブロックを消さない前提) 動的な prevent_destroy 設定から消しても実物を残す destroy = false(後述。Terraform 1.16 にもある) 静的評価: backend 設定に変数が使える(1.8〜) Terraform では backend 設定に変数を書けないため、環境ごとに root module を複製するか、外側のツールで生成するのが定番でした。OpenTofu 1.8 からは backend 設定、module の source と version、state 暗号化の設定に var と local を書けます。 Terraform も 1.15 で module の source / version(const = true を付けた変数のみ)、1.17 で required_providers に変数を使えるようになりましたが、backend 設定と暗号化設定には引き続き書けません。OpenTofu 固有の利点はこの 2 か所です。 variable "env" { type = string } terraform { backend "s3" { bucket = "tfstate-${var.env}" key = "network/terraform.tfstate" region = "ap-northeast-1" } } 値はリソースや data source、module の output に依存しないものに限られ、plan 前に確定している必要があります。tofu init -var env=prod のように init 時に渡し、plan / apply でも同じ値を渡します。env.tfvars のようなファイルにまとめて -var-file で渡すのが楽です。これで環境別の root module 複製を 1 つにまとめられます。 module の version を locals で一元管理する使い方もできます(こちらは Terraform 1.15 以降でも可能です)。 locals { vpc_module_version = "5.21.0" } module "vpc" { source = "terraform-aws-modules/vpc/aws" version = local.vpc_module_version } provider の for_each: リージョン別・アカウント別の複製をなくす(1.9〜) alias 付きの provider 設定に for_each を書けます。リージョンやアカウントの一覧を変数で持ち、provider とリソースをまとめて繰り返せます。 variable "aws_regions" { type = map(object({ vpc_cidr_block = string })) } provider "aws" { alias = "by_region" for_each = var.aws_regions region = each.key } resource "aws_vpc" "main" { for_each = var.aws_regions provider = aws.by_region[each.key] cidr_block = each.value.vpc_cidr_block } for_each は alias と組み合わせたときだけ使えます。リージョンごとに provider ブロックとリソースを手書きで複製していた構成は、これで 1 セットになります。 state と plan のクライアント側暗号化(1.7〜) Terraform の state 保護は backend 側の暗号化(S3 の encrypt、GCS の顧客管理鍵など)とアクセス制御に依存します。state ファイルを取得できた人は中身を読めます。 OpenTofu は state と plan をクライアント側で暗号化でき、backend の暗号化とは独立した防御層になります。 terraform { encryption { key_provider "aws_kms" "main" { kms_key_id = var.state_kms_key_id region = "ap-northeast-1" key_spec = "AES_256" } method "aes_gcm" "main" { keys = key_provider.aws_kms.main } state { method = method.aes_gcm.main } plan { method = method.aes_gcm.main } } } 鍵の供給元は PBKDF2 のパスフレーズ、AWS KMS、GCP KMS、Azure Key Vault、OpenBao、外部コマンドから選べます。鍵や方式を切り替えるときは fallback ブロックで旧方式を残しておくと、読み込みは旧方式に自動で倒れ、書き込みは新方式で行われます。 注意点はデフォルトでは無効なことです。terraform { encryption { ... } } に key_provider、method、state、plan を書いて初めて有効になります。「OpenTofu にしたから state は安全」ではなく、設定して初めて効く機能として扱ってください。運用では、鍵を state ごとに分け、ローテーションを自動化するのが公式の推奨です。AES-GCM は同じ鍵で暗号化できる回数に上限があるためです。 そのほか: Terraform にもある機能 この章は「乗り換えても失わない機能」の確認です。OpenTofu が先行したものも含め、2026 年 10 月時点で Terraform にも同等の機能があるので、採用理由は前章の 4 つで判断してください。 機能 OpenTofu Terraform S3 ネイティブロック(use_lockfile = true) 1.10 1.10(1.11 で GA) Ephemeral 値 1.11 1.10 write-only 属性 1.11 1.11 lifecycle { destroy = false } 1.12 1.16 module の source / version に変数 1.8 1.15 OCI(Open Container Initiative)レジストリからの module / provider 取得 1.10 なし(1.17 までの CHANGELOG に記載なし。1.12 の「OCI Object Storage backend」は Oracle Cloud の話で別物) S3 ネイティブロック S3 backend に use_lockfile = true を書くと、DynamoDB なしでロックが取れます。state 用の DynamoDB テーブルを環境ごとに作っていた構成では、そのテーブルを消せます。 terraform { backend "s3" { bucket = "tfstate-prod" key = "network/terraform.tfstate" region = "ap-northeast-1" use_lockfile = true } } Ephemeral 値と write-only 属性 Ephemeral 値は、plan や apply の実行中だけメモリ上に存在し、state にも plan ファイルにも保存されない値です。write-only 属性は、provider が「書き込みのみ」と宣言した属性で、パスワードのように設定はするが state に残したくない値に使います。どちらも「秘密情報が state に残る」問題への対処で、前章のクライアント側暗号化と組み合わせると、state に残さない・残ったものは暗号化する、の二段構えになります。 destroy = false(OpenTofu 1.12〜、Terraform 1.16〜) リソースが設定から消えたとき、replace が必要なとき、tofu destroy のときに、実物を壊さず state から外すだけ(forget) にします。 resource "aws_s3_bucket" "archive" { bucket = "archive-${var.env}" lifecycle { destroy = false } } plan の action が destroy ではなく forget になります。replace が必要な場合は forget してから新規作成します 一度 apply すると設定が state に残り、true に戻すか引数を消すまで destroy は計画されません destroy = false があると prevent_destroy は効きません 定数の true / false のみで、変数は使えません tofu destroy は forget 対象を残すため非ゼロで終了します。CI で回すなら tofu destroy -suppress-forget-errors でゼロ終了にできます(1.12〜) 同じアドレスで再定義すると新規作成を試みるので、実物が残っていれば失敗します 使いどころは、管理を OpenTofu から別の仕組みに移すときや、実物を残したまま module 構成を組み替えるときです。removed { destroy = false } を毎回書く代わりに、リソース側で宣言しておけます。Terraform 1.16 の destroy = false も「state から外すだけで実物は残す」という趣旨は同じですが、定数のみか・prevent_destroy との優先関係・destroy コマンドの終了コードが同じかは Terraform 側のドキュメントに記載がないため、Terraform で使う場合は挙動を確認してください。 OCI レジストリ ここでの OCI は Open Container Initiative、つまりコンテナイメージと同じレジストリのことです。module は oci: スキームの source で、provider は provider ミラーとして OCI レジストリから取得できます。社内の module や provider を配布するために独自の仕組みを持っている場合、既存のコンテナレジストリに相乗りできます。 乗り換える価値がある構成、差が小さい構成 効く構成 環境ごとに root module を複製している(静的評価で 1 つにできる) リージョンやアカウントをまたいで provider とリソースを複製している(provider の for_each) count = var.x ? 1 : 0 と [0] 参照が多い(enabled) 本番だけ削除防止を効かせるために環境別の定義を持っている(動的な prevent_destroy) state に秘密情報が入り、backend 側の暗号化だけでは不安がある(クライアント側暗号化) 差が小さい構成 単一環境・単一リージョンで、既存の Terraform 構成が安定している 上の構成パターンに当てはまらず、ライセンスの保険だけが動機 後者でも乗り換えを否定するものではありませんが、「ライセンスの保険」以上の理由は出しにくいと考えてください。 まとめ OpenTofu の採用理由はライセンスだけでなく、lifecycle の enabled と動的な prevent_destroy(1.11 / 1.12)、backend と暗号化設定への静的評価(1.8)、provider の for_each(1.9)、state と plan のクライアント側暗号化(1.7)という、Terraform 1.17 時点にはない機能にあります S3 ネイティブロック、Ephemeral 値、write-only 属性、destroy = false、module source への変数は Terraform にもあるので、採用理由ではなく「乗り換えても失わない機能」として扱います。Terraform は版ごとに差を埋めてきているので、比較は版付きで見直してください state 暗号化はデフォルト無効です。採用したら設定を忘れないでください 乗り換える価値は、環境・リージョンの複製や count による出し分けがどれだけあるかで決まります 参考 OpenTofu: The enabled Meta-Argument OpenTofu: Resource Behavior(lifecycle の prevent_destroy と destroy) OpenTofu 1.8: What's new(静的評価) OpenTofu: Provider Configuration(provider の for_each) OpenTofu: State and Plan Encryption OpenTofu: S3 backend(use_lockfile) OpenTofu CHANGELOG: v1.8 / v1.9 / v1.10 / v1.11 / v1.12 Terraform CHANGELOG: v1.10 / v1.11 / v1.15 / v1.16 / v1.17 Terraform: Backend Configuration(backend に変数は不可) Terraform: The lifecycle Meta-Argument(引数はリテラルのみ) Terraform: Sensitive Data in State(state の暗号化は backend 依存) The OpenTofu Manifesto(ライセンス変更の経緯)

  6. TerraformでLambda Web Functions対応がされたかも terraform-provider-aws#50452

    18 likes · 3 reposts · 927 views
  7. Amazon ECS Gateway: managed, shared ingress for ECS services (and the traps to avoid) Originally published in Spanish on CloudAcademy.ar. On October 20, 2026, AWS launched Amazon ECS Gateway, an account-level resource that owns ingress for your ECS services. Instead of every service carrying its own Application Load Balancer, listener, target group, security group and certificate, a platform team defines a gateway once and services opt in with a single parameter on create-service or update-service. ECS provisions everything underneath and packs services onto shared ALBs, up to 25 services per load balancer. If you have ever written an internal Terraform module "so teams don't have to think about the ALB", you already know the problem this solves. The difference is that AWS now maintains that module, and it comes with compatibility rules, quotas and a couple of sharp edges worth knowing before you move production traffic. TL;DR - A gateway has its own ARN and provisions ALBs, HTTPS listeners, listener rules, target groups, security groups, ACM certificates and one hostname per service. - Platform teams create gateways and associate them with clusters. App teams add a gateway connector that names a port from the task definition. - Each service gets https://<unique-id>.ecs.<region>.on.aws. Up to 25 services share one ALB via host-based routing. - HTTPS on port 443 only, awsvpc network mode only (EC2, Fargate, ECS Managed Instances), same account only. - No charge for the gateway itself. You pay for ALBs, public IPv4, logs, metrics and data transfer. - Available in all commercial Regions where ECS runs. - The biggest trap: update-gateway replaces the entire configuration. !Amazon ECS Gateway architecture ECS Gateway architecture: platform declares ingress, each service gets a route on a shared ALB. Image: AWS. The model: gateway, association, connector, route | Concept | What it is | |---|---| | Gateway | Account-level resource, unique name per account and Region | | Gateway-cluster association | Many-to-many: up to 10,000 clusters per gateway, 5 gateways per cluster | | Gateway connector | Service parameter that connects it to every compatible gateway in its cluster | | Gateway route | One service-to-gateway connection, with status, URL and underlying resources | Creating a gateway provisions nothing. Associating it with a cluster changes nobody's traffic. Only when a service with a connector deploys does ECS find a compatible gateway, place the service on an ALB with free capacity (or create one), and create the per-service certificate, hostname, rule, target group and security group. !Responsibilities diagram How ECS picks a gateway (read this twice) The connector does not select a gateway by name or ARN. It attaches to every gateway in the cluster that: 1. matches the connector's accessTypes filter, if any (PUBLIC = internet-facing, PRIVATE = internal), 2. is in the same VPC as the service, and 3. covers every Availability Zone the service runs in. No match, and the operation fails. Several matches, and the service is connected to all of them. The docs flag the consequence explicitly: a service that must never be internet-reachable needs a PRIVATE filter. Without it, if someone later associates an internet-facing gateway with the cluster, your internal service is exposed on its next deployment. Any redeploy will do. !Console: create gateway Creating a gateway in the ECS console. Image: AWS. What the platform team controls Immutable at creation: name, subnets (VPC and AZ coverage), IP address type (ipv4, dualstack default, dualstack-without-public-ipv4) and scheme. The listener is always HTTPS:443. Mutable: inboundSecurityGroup, maxAlbCount (default 10, so 250 services), webACLArn, httpDesync (default defensive), S3 access logs, testTrafficRules (a header that routes requests to the new revision during blue/green or canary), deletionProtection (default true) and propagateTags. Raise maxAlbCount before you need it: a service that opts in at capacity fails its deployment, and raising the limit afterwards does not retry it. Hands-on with the AWS CLI Infrastructure role: aws iam create-role --role-name ecsInfrastructureRoleForGateways \ --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs.amazonaws.com"},"Action":"sts:AssumeRole"}]}' aws iam attach-role-policy --role-name ecsInfrastructureRoleForGateways \ --policy-arn arn:aws:iam::aws:policy/AmazonECSInfrastructureRoleForGatewayHostSharedALB Gateway with access logs and a test-traffic header: aws ecs create-gateway --name platform-public \ --infrastructure-role-arn arn:aws:iam::123456789012:role/ecsInfrastructureRoleForGateways \ --configuration '{"hostSharedAlb":{"scheme":"internet-facing", "networkConfiguration":{"subnets":["subnet-aaa111","subnet-bbb222","subnet-ccc333"],"ipAddressType":"dualstack"}, "maxAlbCount":20,"httpDesync":"monitor", "accessLogs":{"destination":{"s3":{"bucket":"my-alb-logs","prefix":"gateway"}}}, "testTrafficRules":{"header":{"name":"x-test-traffic","values":["canary"]}}}}' aws ecs associate-gateway-with-cluster --gateway platform-public --cluster production Name the port in the task definition (portMappings[].name, e.g. web), then connect the service: aws ecs create-service --cluster production --service-name payments-api \ --task-definition payments-api:7 --desired-count 3 --launch-type FARGATE \ --network-configuration 'awsvpcConfiguration={subnets=[subnet-priv1,subnet-priv2,subnet-priv3],securityGroups=[sg-0123abcd],assignPublicIp=DISABLED}' \ --deployment-configuration '{"strategy": "BLUE_GREEN"}' \ --gateway-connectors '[{"portName":"web","filters":{"accessTypes":["PUBLIC"]},"healthCheck":{"healthCheckPath":"/health"}}]' Get the URL from the service revision: DEPLOY_ARN=$(aws ecs list-service-deployments --cluster production --service payments-api \ --query 'serviceDeployments[0].serviceDeploymentArn' --output text) REV_ARN=$(aws ecs describe-service-deployments --service-deployment-arns "$DEPLOY_ARN" \ --query 'serviceDeployments[0].targetServiceRevision.arn' --output text) aws ecs describe-service-revisions --service-revision-arns "$REV_ARN" \ --query 'serviceRevisions[0].ecsManagedResources.gatewayConnections' Wait for ACTIVE. CREATE_FAILED won't fix itself by waiting. Gotchas - update-gateway replaces everything. Send only maxAlbCount and your WAF is detached, logs are turned off, the test header disappears and deletion protection resets. Always describe-gateway first. - Health check changes replace the target group, which fails on ROLLING deployments. Get it right on first connect, or use BLUE_GREEN/CANARY. - Default subnets come from the default VPC, which rarely matches your services. - No self-repair if someone edits managed resources by hand, and no consolidation of half-empty ALBs. - Not for Express Mode services, one connector per service, same account only. - Terraform: support is still an open request (issue #50573, filed October 21). - Custom domains aren't covered in the current docs; services get on.aws hostnames. Pricing No gateway charge. Reference prices in us-east-1: ALB at $0.0225/hour plus $0.008 per LCU-hour; public IPv4 at $0.005/hour; public ACM certificates are free. My own back-of-the-envelope for fixed costs only (730 hours, three AZs): 30 services with one ALB each come to about $821/month in ALB hours plus public IPv4. The same 30 services on a gateway fit in two ALBs, about $55/month. LCU charges follow traffic and don't disappear. And with 25 rules on a shared listener you go past the 10 free rules, so the rule-evaluation dimension starts counting. If clients support IPv6, dualstack-without-public-ipv4 removes the IPv4 line entirely. Availability and what to check It's in every commercial Region with ECS, including sa-east-1 (São Paulo). Everything it creates lives in your account and Region. Multi-account setups need one gateway per account. Lock down associate-gateway-with-cluster with IAM, because that action decides what becomes exposed on other teams' next deployments. Is it worth it? For teams running dozens of HTTP services on ECS and maintaining shared ALBs by hand or through internal modules: yes. The savings are real, and the split between platform and app teams is the one platform teams want. If you rely on path-based rules, custom domains, mTLS, NLBs or ALB-native OIDC authentication, wait: none of that shows up in the current docs. My take: the shared ALB isn't the news; that was always possible. The news is that AWS now owns the full lifecycle: create, place, scale out to more ALBs, clean up. It mirrors what the AWS Load Balancer Controller's IngressGroups and the Kubernetes Gateway API do on EKS, with separate roles for whoever defines infrastructure and whoever publishes routes. What worries me is that "connect to every compatible gateway" plus "associations apply on next deploy" turns a platform action into an exposure change for someone else's service. My rule: every connector gets an explicit accessTypes filter, always, and very few people can associate gateways. Resources - What's New announcement - AWS News Blog: Introducing Amazon ECS Gateway - Docs: ECS Gateway overview - Docs: create and manage a gateway - Docs: connect services to a gateway - Elastic Load Balancing pricing - Terraform AWS provider issue #50573

  8. cdk8s vs Tanka vs Kapitan for Kubernetes config Pick cdk8s if your team writes TypeScript and wants the compiler to reject a bad value before anything renders. Pick Tanka if you want a small, fast, Kubernetes-only toolchain and accept Jsonnet as the language. Pick Kapitan if one inventory has to drive Kubernetes and Terraform and you would rather keep values in YAML than maintain template code. All three rendered the same app to identical manifests and passed the derived-value test that Helm and Kustomize failed in the companion post. The example builds the app with each tool, and ./check exits 0 only when the normalized manifests match per environment. Versions, commands and raw output behind every number are in its NOTES.md. The app and the check The spec is the companion's: namespace shop, apps web and api with a Deployment, Service and ConfigMap each, restricted Pod Security, dev and prod, PodDisruptionBudgets in prod only, and an api ConfigMap entry web_url built from the web Service port. - Tanka 0.39.4, jsonnet-bundler 0.6.0, k8s-libsonnet 1.36. - cdk8s 2.70.111 in TypeScript 5.9.3, using the generated low-level Kube* classes for Kubernetes 1.36. - Kapitan 0.36.3 with the kadet-hub kubernetes generator 1.2.0 pinned by digest, as in the companion minus endpoints.json. check sorts objects and keys and drops one label, app.kubernetes.io/managed-by, which only the Kapitan generator sets and which names the tool. Nothing else is ignored. Changing one replica count in a copy makes it exit 1. $ ./check dev: tanka = kapitan (6 objects) dev: cdk8s = kapitan (6 objects) prod: tanka = kapitan (8 objects) prod: cdk8s = kapitan (8 objects) How much you write Hand-written files only; lock files, fetched libraries and generated code are listed separately. | | web only | both apps | fetched or generated | |---|---|---|---| | Tanka | 8 files, 138 lines | 8 files, 167 lines | k8s-libsonnet, 30037 lines | | cdk8s | 5 files, 148 lines | 5 files, 159 lines | imports/k8s.ts, 41214 lines, committed | | Kapitan | 5 files, 65 lines | 6 files, 101 lines | generator, 4166 lines Python | For the Helm vs Kustomize vs Jsonnet comparison: Helm needed 156 lines and Kustomize 299 for both apps in the companion. The gap is about who owns the template. Tanka and cdk8s ship building blocks, not an opinion on what a Deployment looks like, so the example carries its own: lib/shop/app.libsonnet (58 lines) and app.ts (87 lines). Both spell out fields Kubernetes would default, such as probe thresholds and defaultMode: 420, to match the generator. In Kapitan the template is the generator, maintained elsewhere and pinned by digest. cdk8s has an opinionated layer too, cdk8s+. An 11-line cdk8s-plus-36 program for the web Deployment produced a cdk8s.io/metadata.addr selector, 1000m/512Mi requests, 1500m/2048Mi limits, a read-only root filesystem and a TCP startup probe. Reasonable defaults, but not the spec's, so the example stays on the low-level classes. Adding the second app | | files changed | lines added | lines removed | |---|---|---|---| | Tanka | 3 | 29 | 0 | | cdk8s | 1 | 16 | 5 | | Kapitan | 3 | 38 | 2 | All three reuse their template, so api is configuration only. cdk8s is smallest partly through layout: its per-environment values are one object literal per line, the Jsonnet and YAML files use one line per field. Helm needed 25 lines here and Kustomize 149. A value derived from another All three compute web_url from the web Service port. In a copy I changed only that port to 8081 in each tool. check still passed, and all three rendered web_url: http://web.shop.svc:8081. In the same test Helm and Kustomize rendered the stale :80 without an error. For Tanka vs Helm and cdk8s vs Helm this is the main difference: a language lets one value reference another, separate Helm values files cannot. The mechanisms differ. Jsonnet binds $._config late, so an environment that overrides the web port also changes the api URL. In cdk8s it is an ordinary variable, so the dependency follows your code structure. Kapitan interpolates ${...} across the whole inventory, so any class or target can reference any value in another file. Typos and type safety I misspelled pdb_min_available as pdb_min_availabe in the prod web values of each tool: | | result | |---|---| | Tanka | renders, exit 0, web PodDisruptionBudget missing | | cdk8s | synth fails: error TS2561: ... 'pdbMinAvailabe' does not exist in type 'Sizing'. Did you mean to write 'pdbMinAvailable'? | | Kapitan | compiles, exit 0, web-scaling.yaml missing | cdk8s catches it because the example declares an interface for its values, and the generated imports type every Kubernetes field for the editor. Jsonnet has no types: reading a missing field fails, adding a misspelled one does not, unless you write asserts. jsonnet-language-server adds completion. Kapitan's inventory is YAML, and neither Kapitan nor the generator rejected the unknown key. An output diff in CI, like check, caught it in all three. Toolchain and speed Install is one run with cold caches and depends on the network. Node.js 26 and Python 3.13 were already present and are not counted. Render covers both environments, five warm runs. | | install | on disk | render | |---|---|---|---| | Tanka | 12.1 s for tk and jb, 3.4 s jb install | 29 MB + 7.3 MB | 0.10 to 0.11 s | | cdk8s | 4.2 s npm ci, 173 packages | 95 MB | 3.46 to 3.59 s | | Kapitan | 63.1 s uv run, 89 packages; 13.3 s generator verify and pull | 285 MB + 6.2 MB | 1.61 to 1.67 s | Tanka is two static Go binaries and by far the fastest. Much of the cdk8s time is ts-node type-checking the 41214-line import file: transpile-only, the same synth took 2.27 to 2.36 s. Kapitan reports 0.68 s for the compile, the rest is uv run and Python startup. Its install is large because the base package depends on cloud SDKs for its secret backends: google-api-python-client alone is 112 of the 267 MB installed. Reuse and packages Tanka libraries are Git repositories that jsonnet-bundler pulls and locks by commit, with no central registry. jsonnet-bundler had no commits in the last 12 months and its latest release, v0.6.0, dates from August 2024. cdk8s uses npm or the package manager of its other languages, and Construct Hub indexes published constructs. The kadet-hub catalog lists 36 Kapitan generators, each an OCI artifact with a build attestation. The registry is young: created on 2026-10-08, one human committer so far. All three consume Helm charts: Tanka through tanka-util, cdk8s through cdk8s import helm: and its Helm construct, Kapitan through its helm input type. Kapitan and Jsonnet Kapitan has a jsonnet input type, so the choice is less exclusive than it looks. I pointed a Kapitan target at the unchanged Tanka library and the vendored k8s-libsonnet, with an 11-line main.jsonnet that reads the prod values from the inventory. After the same normalization the output matched tk show environments/prod, all 8 objects. A team with a Jsonnet codebase can keep it and add inventory, refs and non-Kubernetes outputs, giving up tk diff and tk apply against a cluster. Output beyond Kubernetes Tanka and cdk8s render Kubernetes objects. Plain Jsonnet can emit Terraform's JSON syntax, outside Tanka. CDKTF, the Terraform counterpart of cdk8s, was archived on 10 December 2025 with no further updates. Kapitan compiles any output from one inventory, and kadet-hub lists Terraform generators for AWS, AzureRM, Google Cloud and Open Telekom Cloud, all at 0.1.x. GitOps Argo CD renders Helm, Kustomize and plain Jsonnet directories natively, Flux renders Helm and Kustomize. None of the three tools is native to either. A Tanka environment does not fit Argo CD's Jsonnet support: tk eval returns nested objects (apps.web.deployment) that Tanka flattens, and the namespace comes from spec.json. The usual routes are an Argo CD config management plugin that runs the tool in the repo server, or rendering in CI and committing the YAML or pushing it with flux push artifact. Tanka has tk export for that, and Kapitan always writes files. cdk8s has one more option: cdk8s synth --format helm writes a chart with Chart.yaml and templates, which both Argo CD and Flux deploy natively. Project activity Read-only GitHub API on 2026-10-17, window from 2025-10-17. Human commits exclude bot and automation accounts. | repository | stars | commits | human commits (authors) | releases | latest | |---|---|---|---|---|---| | grafana/tanka | 2690 | 500 | 41 (14) | 17 | v0.39.4, 2026-10-08 | | cdk8s-team/cdk8s | 4859 | 499 | 7 (4) | 0 | umbrella repo | | cdk8s-team/cdk8s-core | 87 | 578 | 0 | 90 | v2.70.111, 2026-10-12 | | cdk8s-team/cdk8s-cli | 41 | 479 | 8 (4) | 125 | v2.207.67, 2026-10-13 | | cdk8s-team/cdk8s-plus | 163 | 635 | 8 (6) | 330 | cdk8s-plus-37 v2.0.0, 2026-10-16 | | kapicorp/kapitan | 1931 | 135 | 93 (11) | 6 | v0.36.3, 2026-07-03 | | kadet-hub/registry | 1 | 716 | 711 (1) | 5 | index-47, 2026-10-16 | 441 of Tanka's 500 commits are Renovate updates. All 578 cdk8s-core commits were automated dependency upgrades; its frequent releases carry those. Kapitan releases less often and has the most human commits of the three tools. Running it You need tk and jb, Node.js with npm, and uv, plus oras and a logged-in gh for the first generator fetch: $ git clone https://github.com/kadet-hub/examples $ cd examples/config-tools $ ./check The first run installs dependencies from the lock files and verifies the generator's attestation before pulling it by digest; the companion post covers what that fetch does not check. Originally published at kadet-hub.org.

  9. YouTube · · YouTube description · opskit tools · hashicorp/terraform

    PHP2Shell Critical RCE, LiteLLM Credential Theft, Terraform 1.17 GA | DevOps News PHP2Shell Critical RCE, LiteLLM Credential Theft, Terraform 1.17 GA | DevOps News This week's top DevOps and AI news, curated and analysed for platform teams, SREs, and AI/LLM developers. ## Chapters 00:00 DevOps and AI Highlights 00:10 PHP patches critical PHP2Shell RCE vulnerabilities 00:36 Compromised LiteLLM release steals credentials via Python startup 01:06 Terraform 1.17 adds minimal refresh and policy GA 01:32 GitHub shifts repository infrastructure and traffic to Azure 02:02 Amazon ECS Gateway automates ALB provisioning and ingress 02:34 Railway urges secret rotation after potential breach 02:59 Google and AWS bring native PyTorch beyond Nvidia 03:33 Curl moves low-severity vulnerability reports to public GitHub 04:03 Anthropic releases always-on Claude Duet agent 04:25 Claude Generates Mathematical Proofs for Code Correctness 04:46 Signing Off 📰 Read the original sources: • PHP patches critical PHP2Shell RCE vulnerabilities securityweek.com • Compromised LiteLLM release steals credentials via Python startup microsoft.com • Terraform 1.17 adds minimal refresh and policy GA github.com/hashicorp/terraform/releases/tag/v1.17… • GitHub shifts repository infrastructure and traffic to Azure github.blog • Amazon ECS Gateway automates ALB provisioning and ingress aws.amazon.com • Railway urges secret rotation after potential breach bleepingcomputer.com • Google and AWS bring native PyTorch beyond Nvidia thenewstack.io • Curl moves low-severity vulnerability reports to public GitHub theregister.com • Anthropic releases always-on Claude Duet agent the-decoder.com • Claude Generates Mathematical Proofs for Code Correctness the-decoder.com --- Subscribe for weekly DevOps + AI news: opskit.tools #devops #ai #kubernetes #sre #platformengineering

    2 likes · 5 views
  10. GitHub ActionsでTerraformの品質チェックを自動化する はじめに 普段の業務では、Terraformを利用したAWSインフラの設計・構築に取り組んでいます。 Terraformの設定変更時には、フォーマットや構文のチェックが重要です。ローカルでも実行できますが、その実行結果はGitHub上に共有されないため、PRのレビュアーがチェック結果を確認しにくいという課題があります。 そこで今回は、GitHub Actionsを利用して、PR作成時にTerraformの品質チェックを自動実行し、チェック結果をGitHub上で確認できるようにしました。 今回やること PR作成時に、以下の3つを自動実行します。 terraform fmt:Terraformコードのフォーマットをチェックする terraform init:Terraformの初期化を行う terraform validate:Terraformの設定を検証する 今回はTerraformの設定ファイルがリポジトリのルートディレクトリにあることを前提としています。 GitHub Actionsのワークフロー 今回作成したワークフローは以下のとおりです。 name: Terraform Quality Check on: pull_request: permissions: contents: read jobs: terraform-quality: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v7 - name: Setup Terraform uses: hashicorp/setup-terraform@v4 - name: Check formatting run: terraform fmt -check -recursive - name: Initialize Terraform run: terraform init -backend=false - name: Validate Terraform run: terraform validate ※ Actionのバージョンは、利用時に公式リポジトリで最新バージョンや互換性を確認してください。 各処理の役割 1. PR作成時にワークフローを実行する on: pull_request: pull_request を指定することで、PRに関連するイベントを契機にワークフローが実行されます。 これにより、PR上でチェック結果を確認できるようになります。 2. Terraformのフォーマットをチェックする - name: Check formatting run: terraform fmt -check -recursive terraform fmt は、Terraformの設定ファイルを標準的な形式に自動整形するコマンドです。 一方、-check を指定すると、自動整形は行わず、フォーマットが正しいかをチェックします。また、-recursive を指定することで、サブディレクトリも対象にできます。 フォーマットに問題がある場合は、コマンドが失敗します。 ローカルでは terraform fmt -recursive で自動整形し、GitHub Actionsでは terraform fmt -check -recursive で修正漏れを検出する方針にしました。 3. Terraformを初期化する - name: Initialize Terraform run: terraform init -backend=false terraform init は、Terraformの実行に必要なプロバイダーなどを初期化するコマンドです。 今回は -backend=false を指定しています。 このオプションにより、バックエンドの初期化をスキップできます。例えば、S3などをTerraformのState保存先として設定している場合でも、バックエンドへの接続・初期化を避けて検証を進められます。 なお、バックエンドをスキップしても、プロバイダーやモジュールのダウンロードが発生する場合があります。 4. Terraformの設定を検証する - name: Validate Terraform run: terraform validate terraform validate は、Terraformの構文や設定の内部的な整合性を検証するコマンドです。 例えば、設定の構文エラーや、リソースの引数・属性の指定に問題がある場合などを検出できます。 ただし、AWS上にリソースを作成できるか、IAM権限が十分か、設計が業務要件を満たしているかといったことまでは検証できません。 実行前には、terraform init などで必要な初期化を済ませておく必要があります。 実際に動かしてみた 作成したワークフローをPRで実行し、各ステップの結果を確認しました。 Check formatting:成功 Initialize Terraform:成功 Validate Terraform:成功 terraform validate では、以下のメッセージが表示されました。 Success! The configuration is valid. 一方、terraform fmt -check -recursive は、問題がなければ特にメッセージが表示されない場合があります。GitHub Actionsのステップが成功していることを確認しました。 このように、PR上で各チェックの実行結果を確認できることが分かりました。 やってみて学んだこと 今回、特に学びになったのは、Terraformのコマンドをローカルで実行することと、CIで自動実行することの違いです。 ローカルでチェックするだけでなく、PR作成時に自動実行することで、チェックの実行漏れを防ぎやすくなり、結果もGitHub上で確認できます。 また、各コマンドには異なる役割があります。 terraform fmt -check:フォーマットのチェック terraform init -backend=false:バックエンドを初期化せずにTerraformを初期化 terraform validate:設定の構文や内部整合性の検証 これらを組み合わせることで、AWSへのデプロイを行う前に、Terraformコードの基本的な品質を確認できるようになります。 まとめ 今回は、GitHub Actionsを使って、PR作成時にTerraformの品質チェックを自動実行する仕組みを作りました。 これまではローカルで実行していたチェックをCIに組み込むことで、PR上で結果を確認できるようになりました。 今後は、Terraformのセキュリティスキャンやテストなども組み合わせ、PRの段階で問題を検出できる仕組みを少しずつ改善していきたいと思います。 参考 Terraform fmt Terraform init Terraform validate GitHub Actions ワークフロー構文 actions/checkout hashicorp/setup-terraform

Trending awards, every completed day and week
Gold
41st place finishes
Silver
92nd place finishes
Bronze
43rd place finishes
Awarded repositories
7Owned by hashicorp now

Repositories

Ordered by gold, then silver, then bronze.

  1. ottoBest: 1st by stars, 554 stars130
  2. waypointBest: 1st by stars, 618 stars112
  3. boundaryBest: 1st by stars, 676 stars110
  4. hashicat-awsBest: 1st by forks, 98 forks110
  5. tfc-workshops-sentinelBest: 2nd by forks, 68 forks012
  6. packerBest: 2nd by stars, 150 stars010
  7. vaultBest: 2nd by stars, 751 stars010

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.