AWSTemplateFormatVersion: "2010-09-09"
Description: >
  Forgecroft AWS OIDC integration — federated, zero-credentialed access.

  Deploy this template once per AWS account you want Forgecroft to manage.
  It creates:
    1. An IAM OIDC identity provider that trusts Forgecroft's issuer.
    2. ForgecroftPlanRole (read-only) — assumed during the plan phase.
    3. ForgecroftApplyRole (write) — assumed during the apply phase.

  Forgecroft signs short-lived JWTs with run-scoped claims (org_id, workspace_id,
  run_id, phase). The trust policies below condition on those claims so:

    - Only YOUR Forgecroft org can assume these roles.
    - Plan-phase JWTs only assume the plan role; apply-phase JWTs only assume apply.
    - No long-lived AWS credentials ever leave your account.

  After deploy, paste the two role ARNs from the Outputs into your Forgecroft
  credential as type "aws_oidc".

Parameters:
  ForgecroftHostname:
    Type: String
    Default: "api.forgecroft.com"
    Description: >
      Hostname of the Forgecroft OIDC issuer (no scheme).
      Default is correct for the managed SaaS; override only for self-hosted
      Forgecroft deployments. The full issuer URL is "https://<hostname>".

  OrgId:
    Type: String
    Description: >
      Your Forgecroft organization UUID. Found in the Forgecroft dashboard under
      Settings → Organization. Embedded in the trust policy so only your org's
      runs can assume these roles.
    AllowedPattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
    ConstraintDescription: "Must be a UUID (e.g. 11111111-2222-3333-4444-555555555555)"

  AllowedRegions:
    Type: String
    Default: "us-east-1,us-west-2"
    Description: >
      Comma-separated list of regions where Forgecroft is allowed to APPLY changes.
      Plans (read-only) are not region-restricted.

  Audience:
    Type: String
    Default: "sts.amazonaws.com"
    Description: >
      OIDC audience claim. AWS expects "sts.amazonaws.com" by default.

Resources:

  ForgecroftOIDCProvider:
    Type: AWS::IAM::OIDCProvider
    Properties:
      Url: !Sub "https://${ForgecroftHostname}"
      ClientIdList:
        - !Ref Audience
      # ThumbprintList omitted: AWS auto-derives it from the issuer's TLS chain.

  ForgecroftPlanRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "ForgecroftPlan-${OrgId}"
      Description: >
        Assumed by Forgecroft during the PLAN phase. Read-only by design — this
        is what delivers "zero credentialed write access during plan".
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Federated: !Ref ForgecroftOIDCProvider
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringEquals:
                # AWS condition keys use the issuer hostname as a prefix.
                # The audience the JWT is signed for.
                !Sub "${ForgecroftHostname}:aud": !Ref Audience
                # Phase claim — only plan-phase JWTs can assume this role.
                !Sub "${ForgecroftHostname}:phase": "plan"
                # Org claim — only YOUR org's JWTs can assume this role.
                !Sub "${ForgecroftHostname}:org_id": !Ref OrgId
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/ReadOnlyAccess

  ForgecroftApplyRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "ForgecroftApply-${OrgId}"
      Description: >
        Assumed by Forgecroft during the APPLY phase. Write permissions
        constrained to AllowedRegions.
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Federated: !Ref ForgecroftOIDCProvider
            Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringEquals:
                !Sub "${ForgecroftHostname}:aud": !Ref Audience
                !Sub "${ForgecroftHostname}:phase": "apply"
                !Sub "${ForgecroftHostname}:org_id": !Ref OrgId
      Policies:
        - PolicyName: ForgecroftApply
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: "*"
                Resource: "*"
                Condition:
                  StringLike:
                    aws:RequestedRegion: !Split [",", !Ref AllowedRegions]

Outputs:
  PlanRoleArn:
    Description: "Paste into Forgecroft credential form as plan_role_arn."
    Value: !GetAtt ForgecroftPlanRole.Arn

  ApplyRoleArn:
    Description: "Paste into Forgecroft credential form as apply_role_arn."
    Value: !GetAtt ForgecroftApplyRole.Arn

  OIDCProviderArn:
    Description: "ARN of the IAM OIDC provider — for debugging only."
    Value: !Ref ForgecroftOIDCProvider
