magic-pocket-cli 0.41.1__tar.gz → 0.43.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/PKG-INFO +2 -2
  2. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/django_cli.py +15 -1
  3. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/iam_roles.py +14 -71
  4. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/stage_roles.py +3 -2
  5. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pyproject.toml +2 -2
  6. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/.gitignore +0 -0
  7. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/__init__.py +0 -0
  8. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/__init__.py +0 -0
  9. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/aws_auth.py +0 -0
  10. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/backup_cli.py +0 -0
  11. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/build_cli.py +0 -0
  12. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/cleanup_deprecated_cli.py +0 -0
  13. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/cloudfront_cli.py +0 -0
  14. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/cloudfront_keys_cli.py +0 -0
  15. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/cloudfront_waf_cli.py +0 -0
  16. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/container_cli.py +0 -0
  17. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/deploy_cli.py +0 -0
  18. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/destroy_cli.py +0 -0
  19. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/dsql_cli.py +0 -0
  20. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/image_cli.py +0 -0
  21. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/inbound_cli.py +0 -0
  22. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/interaction.py +0 -0
  23. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/main_cli.py +0 -0
  24. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/migrate_cli.py +0 -0
  25. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/neon_cli.py +0 -0
  26. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/permissions_cli.py +0 -0
  27. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/rds_cli.py +0 -0
  28. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/removed_flags.py +0 -0
  29. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/resource_helper.py +0 -0
  30. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/runtime_config_cli.py +0 -0
  31. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/s3_cli.py +0 -0
  32. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/status_cli.py +0 -0
  33. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/store_url_helper.py +0 -0
  34. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/tidb_cli.py +0 -0
  35. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/upstash_cli.py +0 -0
  36. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/url_helper.py +0 -0
  37. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/vpc_cli.py +0 -0
  38. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/cli/waf_cli.py +0 -0
  39. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/mediator.py +0 -0
  40. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/migrations.py +0 -0
  41. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/__init__.py +0 -0
  42. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/__init__.py +0 -0
  43. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/backup_common.py +0 -0
  44. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/backup_legacy.py +0 -0
  45. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/builders/__init__.py +0 -0
  46. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/builders/codebuild.py +0 -0
  47. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/builders/context_check.py +0 -0
  48. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/builders/depot.py +0 -0
  49. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/builders/docker.py +0 -0
  50. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/builders/dockerignore.py +0 -0
  51. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/cloudformation.py +0 -0
  52. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/ecr.py +0 -0
  53. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/efs.py +0 -0
  54. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/lambdahandler.py +0 -0
  55. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/poll.py +0 -0
  56. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/s3_utils.py +0 -0
  57. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/stack_backed.py +0 -0
  58. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/aws/state.py +0 -0
  59. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/backup.py +0 -0
  60. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/cloudfront.py +0 -0
  61. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/cloudfront_acm.py +0 -0
  62. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/cloudfront_keys.py +0 -0
  63. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/cloudfront_waf.py +0 -0
  64. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/container.py +0 -0
  65. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/dsql.py +0 -0
  66. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/inbound.py +0 -0
  67. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/inbound_domain.py +0 -0
  68. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/inbound_template.py +0 -0
  69. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/neon.py +0 -0
  70. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/rds.py +0 -0
  71. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/s3.py +0 -0
  72. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/sqs_alert.py +0 -0
  73. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/tidb.py +0 -0
  74. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/upstash.py +0 -0
  75. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/resources/vpc.py +0 -0
  76. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cf_function_api_host.js +0 -0
  77. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cf_function_basic_auth_prelude.js +0 -0
  78. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cf_function_cache_control.js +0 -0
  79. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cf_function_deploy_hash_strip.js +0 -0
  80. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cf_function_host_redirect_prelude.js +0 -0
  81. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cf_function_spa_auth.js +0 -0
  82. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cf_function_spa_fallback.js +0 -0
  83. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cloudfront.yaml +0 -0
  84. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cloudfront_acm.yaml +0 -0
  85. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cloudfront_keys.yaml +0 -0
  86. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/cloudfront_waf.yaml +0 -0
  87. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/container.yaml +0 -0
  88. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/cloudformation/vpc.yaml +0 -0
  89. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/init/django-dotenv.env +0 -0
  90. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/init/django-settings.py +0 -0
  91. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/init/pocket.Dockerfile +0 -0
  92. {magic_pocket_cli-0.41.1 → magic_pocket_cli-0.43.0}/pocket_cli/templates/init/pocket_simple.toml +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: magic-pocket-cli
3
- Version: 0.41.1
3
+ Version: 0.43.0
4
4
  Summary: CLI and deploy tools for magic-pocket.
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: awscrt>=0.19.0
7
7
  Requires-Dist: click>=8.1.7
8
8
  Requires-Dist: deepdiff>=6.7.1
9
9
  Requires-Dist: jinja2>=3.1.3
10
- Requires-Dist: magic-pocket<0.42,>=0.41.1
10
+ Requires-Dist: magic-pocket<0.44,>=0.43.0
11
11
  Requires-Dist: pathspec>=1.0.4
12
12
  Requires-Dist: python-on-whales>=0.68.0
13
13
  Requires-Dist: pyyaml>=6.0.1
@@ -391,10 +391,24 @@ def collectstatic_locally(stage: str, *, link: bool = False):
391
391
  args.append("--link")
392
392
  cmd = _build_python_command(args)
393
393
  project_dir = _get_project_dir(stage)
394
- run(cmd, check=True, cwd=project_dir) # noqa: S603 shell=False + 制御された引数
394
+ run(cmd, check=True, cwd=project_dir, env=_collectstatic_env(stage)) # noqa: S603 shell=False + 制御された引数
395
395
  clear_staticfiles_override_env()
396
396
 
397
397
 
398
+ def _collectstatic_env(stage: str) -> dict[str, str]:
399
+ """collectstatic の subprocess に渡す環境変数。
400
+
401
+ Lambda に注入するのと同じ DEPLOY_HASH を渡し、settings.py の STATIC_URL を
402
+ deploy 後と同じ値にする。pocket が登録する system check (STATIC_URL の形の
403
+ 検査、KN1688) が Lambda の更新前の collectstatic で効くようにするため。
404
+ """
405
+ env = dict(os.environ)
406
+ c = resolve_django_container(Context.from_toml(stage=stage))
407
+ if c and c.envs.get("DEPLOY_HASH"):
408
+ env["DEPLOY_HASH"] = c.envs["DEPLOY_HASH"]
409
+ return env
410
+
411
+
398
412
  @django.command()
399
413
  @click.option("--stage", envvar="POCKET_DEPLOY_STAGE", prompt=True)
400
414
  @click.option("--skip-collectstatic", is_flag=True, default=False)
@@ -14,7 +14,9 @@ pocket.toml と account / region だけで決まる)。
14
14
 
15
15
  [iam] external_roles = true のときは pocket は role を作らない。RoleSpec は
16
16
  「利用者が事前に作るべき role」の定義になり、`pocket permissions roles` が
17
- それを出力し、deploy は verify_role で実際の role と突き合わせる。
17
+ それを出力する。deploy は verify_role で role の存在と信頼先だけを確認し、
18
+ policy の中身は見ない (充足は role の持ち主の責任。pocket の版更新で policy の
19
+ 文面が変わるたびに role の更新を強いない)。
18
20
  """
19
21
 
20
22
  from __future__ import annotations
@@ -508,7 +510,7 @@ def delete_role(
508
510
 
509
511
 
510
512
  class RoleMismatchError(Exception):
511
- """external_roles の role が無い、または pocket が必要とする policy と違う。"""
513
+ """external_roles の role が無い、または pocket の service を信頼していない。"""
512
514
 
513
515
 
514
516
  _SUB_VARIABLE = re.compile(r"\$\{([^}]+)\}")
@@ -544,32 +546,21 @@ def _pseudo_parameter(name: str, region: str, account_id: str) -> str:
544
546
  return values[name]
545
547
 
546
548
 
547
- def verify_role(
548
- iam_client: IAMClient, spec: RoleSpec, *, region: str | None = None
549
- ) -> str:
550
- """external の role が spec どおりかを検査し、ARN を返す。
549
+ def verify_role(iam_client: IAMClient, spec: RoleSpec) -> str:
550
+ """external の role の存在と pocket の service への信頼を検査し、ARN を返す。
551
551
 
552
- pocket が必要とする信頼先・managed policy・inline policy がすべて揃って
553
- いるかを見る。利用者が足した policy は許容する。inline policy は同名の
554
- 文書が一致すること (`pocket permissions roles` の出力をそのまま使う前提)。
555
- region は inline policy が ${AWS::Region} を含む場合に要る。
552
+ policy (managed / inline) の中身は検査しない。role の持ち主は組織の流儀
553
+ (標準の許可セット・命名・boundary) で policy を組むため、pocket の出力との
554
+ 文面一致を求めると、pocket の版更新で文面が変わるたびに全 project の deploy
555
+ が止まる。必要な権限は `pocket permissions roles` が示し、充足は持ち主が
556
+ 保証する。
556
557
  """
557
558
  role = _get_external_role(iam_client, spec.name)
558
- account_id = role["Arn"].split(":")[4]
559
- problems: list[str] = []
560
559
  if not _trusts_service(role.get("AssumeRolePolicyDocument", {}), spec.service):
561
- problems.append("信頼ポリシーが %s を許可していません" % spec.service)
562
- problems += _managed_policy_problems(iam_client, spec)
563
- problems += _inline_policy_problems(
564
- iam_client,
565
- spec,
566
- spec.resolved_inline_policies(region=region or "", account_id=account_id),
567
- )
568
- if problems:
569
560
  raise RoleMismatchError(
570
- "IAM role %s が pocket の必要とする権限と一致しません:\n%s\n"
571
- "`pocket permissions roles` の出力どおりに更新してから再実行してください。"
572
- % (spec.name, "\n".join(" - " + p for p in problems))
561
+ "IAM role %s の信頼ポリシーが %s に sts:AssumeRole を許可していません。"
562
+ "`pocket permissions roles` の assume_role_policy を参考に信頼ポリシーを"
563
+ "直してから再実行してください。" % (spec.name, spec.service)
573
564
  )
574
565
  return role["Arn"]
575
566
 
@@ -587,54 +578,6 @@ def _get_external_role(iam_client: IAMClient, name: str) -> dict[str, Any]:
587
578
  ) from e
588
579
 
589
580
 
590
- def _managed_policy_problems(iam_client: IAMClient, spec: RoleSpec) -> list[str]:
591
- paginator = iam_client.get_paginator("list_attached_role_policies")
592
- attached = {
593
- policy["PolicyArn"]
594
- for page in paginator.paginate(RoleName=spec.name)
595
- for policy in page["AttachedPolicies"]
596
- }
597
- return [
598
- "managed policy %s が付いていません" % arn
599
- for arn in spec.managed_policy_arns
600
- if arn not in attached
601
- ]
602
-
603
-
604
- def _inline_policy_problems(
605
- iam_client: IAMClient, spec: RoleSpec, expected: dict[str, dict[str, Any]]
606
- ) -> list[str]:
607
- problems: list[str] = []
608
- for name, document in expected.items():
609
- try:
610
- actual = iam_client.get_role_policy(RoleName=spec.name, PolicyName=name)
611
- except ClientError as e:
612
- if e.response["Error"]["Code"] != "NoSuchEntity":
613
- raise
614
- problems.append("inline policy %s がありません" % name)
615
- continue
616
- if _normalize_policy(actual["PolicyDocument"]) != _normalize_policy(document):
617
- problems.append("inline policy %s の内容が違います" % name)
618
- return problems
619
-
620
-
621
- def _normalize_policy(value: Any) -> Any:
622
- """意味の同じ policy 文書を同じ値にそろえる。
623
-
624
- IAM を扱う道具 (Terraform 等) は要素 1 つの list を値そのものに変えたり、
625
- list を並べ替えたりする。IAM の評価ではどれも同じ意味になるため、比較では
626
- 区別しない。
627
- """
628
- if isinstance(value, dict):
629
- return {k: _normalize_policy(v) for k, v in value.items()}
630
- if isinstance(value, list):
631
- items = [_normalize_policy(v) for v in value]
632
- if len(items) == 1:
633
- return items[0]
634
- return sorted(items, key=lambda v: json.dumps(v, sort_keys=True))
635
- return value
636
-
637
-
638
581
  def _trusts_service(document: dict[str, Any], service: str) -> bool:
639
582
  statements = document.get("Statement", [])
640
583
  if isinstance(statements, dict):
@@ -40,7 +40,8 @@ def stage_role_specs(context: Context, *, account_id: str) -> list[iam_roles.Rol
40
40
 
41
41
 
42
42
  def verify_stage_roles(context: Context) -> None:
43
- """external_roles の role がすべて揃っているかを deploy の変更前に検査する。"""
43
+ """external_roles の role がすべて存在し pocket の service を信頼しているかを
44
+ deploy の変更前に検査する (policy の中身は見ない)。"""
44
45
  if not context.external_roles or not context.general:
45
46
  return
46
47
  region = context.general.region
@@ -49,7 +50,7 @@ def verify_stage_roles(context: Context) -> None:
49
50
  ]
50
51
  iam = boto3.client("iam", region_name=region)
51
52
  for spec in stage_role_specs(context, account_id=account_id):
52
- iam_roles.verify_role(iam, spec, region=region)
53
+ iam_roles.verify_role(iam, spec)
53
54
 
54
55
 
55
56
  def _codebuild_builder(context: Context) -> CodeBuildBuilder | None:
@@ -1,12 +1,12 @@
1
1
  [project]
2
2
  name = "magic-pocket-cli"
3
- version = "0.41.1"
3
+ version = "0.43.0"
4
4
  description = "CLI and deploy tools for magic-pocket."
5
5
  requires-python = ">=3.10"
6
6
  dependencies = [
7
7
  # lib は同 minor に束縛する。0.x では minor が breaking の単位のため、
8
8
  # 上限なしだと cli を pin した消費者にも lib の破壊的変更が届いてしまう
9
- "magic-pocket>=0.41.1,<0.42",
9
+ "magic-pocket>=0.43.0,<0.44",
10
10
  "click>=8.1.7",
11
11
  "jinja2>=3.1.3",
12
12
  "python-on-whales>=0.68.0",