Commit 082b16eb authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

fix: support env type fullname / indirection with var prefix

parent ae7f206f
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ Retrieve authentication token using API.
|----------------------------|-------------------------------------------------------------------------------------------|-----------------------|
| `serviceAccount`           | Default Service Account to which impersonate with OpenID Connect authentication           | `false` |
| `workloadIdentityProvider` | Default Workload Identity Provider associated with GitLab to [authenticate with OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/google_cloud/) | `false` |
| `envType`                  | The to-be-continuous environment type to retrieve associated Service Account and Workload Identity Provider values (one of `review`, `integ`, `staging` or `prod`).<br/>_Only when `serviceAccount` and `workloadIdentityProvider` are not specified_ | `false` |
| `envType`                  | The to-be-continuous environment type to retrieve associated Service Account and Workload Identity Provider values (one of `review`, `integration`, `staging` or `production`).<br/>_Only when `serviceAccount` and `workloadIdentityProvider` are not specified_ | `false` |

##### How are implicitly determined `serviceAccount` and `workloadIdentityProvider` values?

@@ -44,9 +44,9 @@ When not explicitly set, `serviceAccount` and `workloadIdentityProvider` values

| `envType`        | `serviceAccount` value | `workloadIdentityProvider` value |
| ---------------- | ---------------------- | -------------------------------- |
| `prod`           | `$GCP_PROD_OIDC_ACCOUNT` or `$GCP_OIDC_ACCOUNT` (fallback) | `$GCP_PROD_OIDC_PROVIDER` or `$GCP_OIDC_PROVIDER` (fallback) |
| `production`     | `$GCP_PROD_OIDC_ACCOUNT` or `$GCP_OIDC_ACCOUNT` (fallback) | `$GCP_PROD_OIDC_PROVIDER` or `$GCP_OIDC_PROVIDER` (fallback) |
| `staging`        | `$GCP_STAGING_OIDC_ACCOUNT` or `$GCP_OIDC_ACCOUNT` (fallback) | `$GCP_STAGING_OIDC_PROVIDER` or `$GCP_OIDC_PROVIDER` (fallback) |
| `integ`          | `$GCP_INTEG_OIDC_ACCOUNT` or `$GCP_OIDC_ACCOUNT` (fallback) | `$GCP_INTEG_OIDC_PROVIDER` or `$GCP_OIDC_PROVIDER` (fallback) |
| `integration`    | `$GCP_INTEG_OIDC_ACCOUNT` or `$GCP_OIDC_ACCOUNT` (fallback) | `$GCP_INTEG_OIDC_PROVIDER` or `$GCP_OIDC_PROVIDER` (fallback) |
| `review`         | `$GCP_REVIEW_OIDC_ACCOUNT` or `$GCP_OIDC_ACCOUNT` (fallback) | `$GCP_REVIEW_OIDC_PROVIDER` or `$GCP_OIDC_PROVIDER` (fallback) |

##### How is guessed `envType`?
@@ -55,8 +55,8 @@ When not explicitly set, `envType` is automatically guessed based on [GitLab pre

| `$CI_REF_NAME`     | `envType` value |
| ------------------ | --------------- |
| `master` or `main` | **prod** if `$CI_JOB_STAGE` is one of `publish`, `infra-prod`, `production`, `.post`<br/>**staging** otherwise |
| `develop`          | **integ** |
| `master` or `main` | **production** if `$CI_JOB_STAGE` is one of `publish`, `infra-prod`, `production`, `.post`<br/>**staging** otherwise |
| `develop`          | **integration** |
| _any other branch_ | **review** |

#### Example
+52 −25
Original line number Diff line number Diff line
@@ -8,52 +8,79 @@ from app.gcp_client import get_iam_credentials, get_sts_token

app = FastAPI()


def guess_env_type() -> str:
    ref_name = os.getenv("CI_REF_NAME", "-")
    prod_ref = os.getenv("PROD_REF", "/^(master|main)$/").strip("/")
  integ_ref = os.getenv("INTEG_REF", "/^develop$/").strip("/")

    if re.match(prod_ref, ref_name):
        # could be staging or prod
    if os.getenv("CI_JOB_STAGE", "-") in ["publish", "infra-prod", "production", ".post"]:
      return "prod"
        if os.getenv("CI_JOB_STAGE", "-") in [
            "publish",
            "infra-prod",
            "production",
            ".post",
        ]:
            return "production"
        return "staging"
  elif re.match(integ_ref, ref_name):
    return "integ"
  else:

    integ_ref = os.getenv("INTEG_REF", "/^develop$/").strip("/")
    if re.match(integ_ref, ref_name):
        return "integration"

    return "review"


def get_oidc_account(env_type: str) -> str:
  return os.getenv(f"GCP_{env_type.upper()}_OIDC_ACCOUNT") or os.getenv("GCP_OIDC_ACCOUNT")
def get_var_prefix(env_type: str) -> str:
    if env_type == "review":
        return "REVIEW"
    if env_type == "integ" or env_type == "integration":
        return "INTEG"
    if env_type == "staging":
        return "STAGING"
    if env_type == "prod" or env_type == "production":
        return "PROD"
    raise HTTPException(
        status_code=404, detail=f"Unsupported environment type '{env_type}'"
    )


def get_oidc_account(var_prefix: str) -> str:
    return os.getenv(f"GCP_{var_prefix}_OIDC_ACCOUNT") or os.getenv("GCP_OIDC_ACCOUNT")


def get_oidc_provider(env_type: str) -> str:
  return os.getenv(f"GCP_{env_type.upper()}_OIDC_PROVIDER") or os.getenv("GCP_OIDC_PROVIDER")
def get_oidc_provider(var_prefix: str) -> str:
    return os.getenv(f"GCP_{var_prefix}_OIDC_PROVIDER") or os.getenv(
        "GCP_OIDC_PROVIDER"
    )


@app.get('/ping', response_class=PlainTextResponse)
@app.get("/ping", response_class=PlainTextResponse)
def ping():
    return 'pong'
    return "pong"


@app.get('/token')
@app.get("/token")
def token(
    workload_identity_provider: str = Query(default=None, alias='workloadIdentityProvider'),
    service_account: str = Query(default=None, alias='serviceAccount'),
    env_type: str = Query(default=None, alias='envType'),
    workload_identity_provider: str = Query(
        default=None, alias="workloadIdentityProvider"
    ),
    service_account: str = Query(default=None, alias="serviceAccount"),
    env_type: str = Query(default=None, alias="envType"),
):
    # projects/%s/locations/global/workloadIdentityPools/%s/providers/%s
    if (not workload_identity_provider) or (not service_account):
        # retrieve from TBC standard variables
        if env_type is None:
            env_type = guess_env_type()
        workload_identity_provider = get_oidc_provider(env_type)
        service_account = get_oidc_account(env_type)

        var_prefix = get_var_prefix(env_type)

        workload_identity_provider = get_oidc_provider(var_prefix)
        service_account = get_oidc_account(var_prefix)
        if (not workload_identity_provider) or (not service_account):
            raise HTTPException(
                status_code=400,
                detail=f"Couldn't retrieve implicit OIDC provider/account from env for '{env_type}'"
                detail=f"Couldn't retrieve implicit OIDC provider/account from env for '{env_type}'",
            )

    audience = "//iam.googleapis.com/%s" % workload_identity_provider