hashicorp

Activity

Stars and mentions · Last 30 days, Oct 5 – Nov 3

GitHub stars385
Mentions62
010203040Oct 5Oct 19Nov 3
UTC days · repositories hashicorp owns22 repositories

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 41 post
  1. modules.tf now reviews Terraform module pull requests Reviewing pull requests for terraform-aws-modules has always taken a lot of my time. It was a problem for a very long time, and I recorded livestreams of myself doing it. I cannot skip it: merging something that is not great is a way to disaster and lost trust. AI lets everyone write code now, and coding agents open pull requests for Terraform modules. A person still reads each one. A model already knows how to write good Terraform. For that part I maintain terraform-skill, a skill for Terraform and OpenTofu with testing, module, CI/CD and production patterns. What a model does not know is what we allow and expect in the modules. Can a module create a KMS key? Which regions may examples use? Does this addition belong in the module at all? terraform-aws-modules has no written scope policy, so the model guesses and I read the guess. I released the pieces that write it down and apply it. modulestf is four agent skills for Claude Code and Codex, with a profile of the rules. mtf-facts is the command-line tool that decides the rules a parser can decide. Both are Apache-2.0. The skills run in your agent, on your machine, with your own GitHub login. This is the beginning of the work, and the last section says what I need from other maintainers and contributors. The name modules.tf is older than this. In November 2018 I [announced it](/modules-tf-convert-visual-aws-diagram-into-terraform-configuration/) as a converter from Cloudcraft diagrams to Terraform. That code is on the legacy branch of the modulestf repository, and the name now belongs to the review tool. A profile writes down what the modules allow A profile is the written rules for one group of modules. terraform-aws-modules is the only profile that ships. It holds the templates copied into each module, the required file layout (examples/basic, examples/complete), code conventions such as regions and version floors, the pre-commit gate, the release and pull request title rules, and scope. Each rule has an ID, a severity and a check. compat.variable-removed holds a change for the next major release. coverage.attribute-not-output asks that an attribute a new resource exports is also an output. profile.region-not-allowed fires on an example in a region the rules do not allow. Scope is the part I wanted most, and it lives in SCOPE.md. In terraform-aws-modules a module manages one AWS service, and the repository name says which. The file lists the few resource types any module may add next to its service: IAM roles and policies, a log group, security groups. The list is closed. A KMS key is deliberately not on it, because a key is a service of its own with its own policy, rotation and deletion window. The module takes the key's ARN as an input, and the caller composes. The first block of a type that nothing admits is a ban, even when the type plainly belongs to the same service. The cost is one allow entry in the module's docs/SCOPE.md, landed on the base before the change. SCOPE.md is a policy I adopted for the profile, not an existing one, so it is also the place to argue with me. Scope has its own outcomes. When an addition does not belong, the review says Ban and names where it goes, or Maintainer decision when a person has to decide. When a rule could not be applied, the outcome is Not evaluated, which is an unknown and never a pass. Text inside the pull request, such as "this is in scope", never clears a rule. Four skills apply the profile | Skill | You give it | You get back | |-------|-------------|--------------| | terraform-module-pr-review | A pull request or commit URL, or owner/repo#123 | A verdict and a comment to post, after you confirm | | terraform-module-reviewer | A module checkout and a diff, a base ref or changed files | A list of findings. Read-only, no verdict | | terraform-module-maintainer (early preview) | A change to make, review feedback, a new module or a provider upgrade | Edits in your checkout, the checks it ran, and reply drafts | | change-scope | A proposed addition, in any language or project | Whether it belongs, and where it goes if not | The pull request review calls the reviewer, and both call change-scope. The maintainer applies change-scope before it edits anything, and it is an early preview: expect it to change. The three Terraform skills read provider schemas from HashiCorp's Terraform MCP server and not from memory. Without that server, every rule that needs a provider fact is reported as not run. !The four skills, the terraform-aws-modules profile, mtf-facts and the Terraform MCP server, with the calls between them. A review ends with a verdict and a list of what was not checked On 4 November I asked my agent to run the terraform-module-pr-review skill on a pull request that adds a Regional NAT Gateway mode to terraform-aws-vpc. It came back with two HIGH findings, eight MEDIUM and one LOW, and I posted the result as changes requested. One HIGH finding is a route that counts one gateway while the module makes a route table per private subnet, so only the first table gets the DNS64 route. The other is an example that uses a region the rules do not allow for examples. The last line of the verdict is the one I care about most: Behaviour evidence: 56 changes classified: 0 verified, 3 covered by a plan, 0 inert, 0 refuted, 53 not verified The review counts what it could not check, and it does not count a gap as a pass. The verdict has no judgement of its own. A fixed ladder of seven rules turns the findings and the state of the pull request's checks and threads into one verdict, and the first rule that matches wins. Any HIGH finding gives the verdict Block, which is why #1270 got changes requested. When something could not be checked the verdict is Inconclusive, unless a finding or a failing check already decides it. !A review flows from a pull request reference through a sandboxed checkout, mtf-facts, the reviewer, the verification ladder and a computed verdict to a comment that is posted only after you confirm. The skill clones the pull request into a temporary directory and runs terraform init -backend=false and terraform validate in each example, the ones the change touches first. AWS, GitHub, Terraform and SSH credentials are removed from that environment, the home directory is empty and there is no backend. terraform init downloads the providers and modules the change pins, and terraform validate runs those provider plugins, so a passing terraform validate is evidence, not proof. The skill posts nothing until you confirm the comment and the review event. mtf-facts decides what a parser can decide modules.tf is built so that an AI spends its effort where it helps. A variable with no type, a missing versions.tf and a removed output are facts about files, and a model should not spend tokens finding them. mtf-facts is a Go command-line tool that reads module files and reports those facts: rule results, candidate findings with evidence, interface and schema diffs. It makes no network call and runs no Terraform. What it hands the model is small on purpose. lint --json --ai writes one line with only the parts a reviewer decides on, and leaves out the file index, the interface diff and the schema coverage. bundle turns the full report into the text the reviewer reads, capped at 48 KiB. Over the cap it sheds sections from the lowest priority up, and never the findings or the candidates. I have not published a measured token saving, so treat this as the design and not as a benchmark. brew install modulestf/tap/mtf-facts mtf-facts lint ./my-module --base ../base-tree Three commands are for the person writing a module: lint, ledger for provider coverage, and schema-diff for provider upgrades. The rest are for the review pipeline: affected, depth, bundle, merge, behaviour, claims-eval and fixture-check. lint exits 0 when there are no findings and every rule was decided. It exits 1 on findings and 2 on an error. It exits 3 when there are no findings but at least one rule was not evaluated, so an incomplete check is never reported as a success. Candidates are unconfirmed, and they never change the exit code. The facts repository walks through a real pull request command by command. Behaviour changes are verified with escalating evidence Dropping compact() around a list looks harmless in a diff. Whether it changes anything depends on values the diff does not show. mtf-facts behaviour turns each changed construct into a trigger with one category, and each category takes up to two levels of evidence, simplest first. !Four levels of evidence, L1 offline evaluation, L2 plan-only terraform test, L3 curated fixture with the real provider and L4 the credentialed example plan, with what each needs. L1 to L3 run with the network denied, in a sandbox that a canary proves before any command. On macOS that sandbox is sandbox-exec, on Linux bwrap. When the sandbox is not proven, those levels cannot verify anything. Reading the code supports a claim and never verifies one. A trigger that ends verified, covered by a plan or inert passes. A refuted one blocks. One that is not verified makes the review Inconclusive, unless a finding or a failing check already decides it. In #1270 the two HIGH findings already decided the verdict, so the 53 changes that were not verified did not change it. The review lists them, and the two examples it did not plan, under "Checks that could not run" and does not leave them out. What it will not do No skill runs terraform apply today, writes state or uses a real backend. I plan to add terraform apply, so a review can execute the examples fully and tear them down in a sandboxed environment. That does not exist yet. None of the skills merges, pushes to a pull request or resolves threads. The skills treat instructions found in the code, the pull request text or its comments as data and do not follow them. There is an optional plan pass that runs terraform plan on a short session of a read-only role that the account owner creates. Before planning, a write probe (a dry-run VPC create) must be refused. That probe tests one write action, not the whole policy, and the isolated plan runner is a prototype. Install 1. Install the skills from my agent-plugins marketplace. The three Terraform skills link into each other, so the modulestf plugin ships all four. terraform-skill is in the same marketplace. # Claude Code /plugin marketplace add antonbabenko/agent-plugins /plugin install modulestf@antonbabenko /plugin install terraform-skill@antonbabenko # Codex: add the marketplace, then install modulestf from /plugins codex plugin marketplace add antonbabenko/agent-plugins 2. Add the Terraform MCP server to your agent under the name terraform. 3. Run gh auth login as yourself, and install terraform, git, jq, perl and mtf-facts. Without mtf-facts a pull request review is Inconclusive at best. 4. Ask your agent: review terraform-aws-modules/terraform-aws-lambda#780 This is the beginning I want the other maintainers and contributors of terraform-aws-modules to use this on their pull requests. I cannot see from my side what stands in the way. I want feedback, good and bad. Tell me about a finding that was wrong, a missing rule, or a check you would not trust. Read SCOPE.md for a module you maintain and tell me where it is wrong. It may need an allow entry I did not think of. Open an issue with the pull request link and the rule ID.

  2. 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>

  3. 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 でもサポートなし

  4. 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

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

  6. 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(ライセンス変更の経緯)

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

    18 likes · 3 reposts · 927 views
  8. 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

  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

Achievements

Awards earned by the repositories hashicorp owns. Select an award to embed its badge.

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

Every award

Top-three finishes of these repositories in completed trending days and weeks, newest first.

  1. hashicat-aws
  2. tfc-workshops-sentinel
  3. tfc-workshops-sentinel
  4. hashicat-aws
  5. tfc-workshops-sentinel
  6. waypoint
  7. waypoint
  8. waypoint

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.