{"id":20098634,"url":"https://github.com/pfnet/image-pull-secrets-provisioner","last_synced_at":"2025-05-06T05:32:23.722Z","repository":{"id":232177221,"uuid":"782281648","full_name":"pfnet/image-pull-secrets-provisioner","owner":"pfnet","description":null,"archived":false,"fork":false,"pushed_at":"2024-05-16T10:10:29.000Z","size":231,"stargazers_count":17,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-05-16T11:27:31.006Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pfnet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-05T01:39:40.000Z","updated_at":"2024-05-16T11:27:32.748Z","dependencies_parsed_at":"2024-04-11T09:42:35.304Z","dependency_job_id":"5b43438f-6312-4e31-b8ce-4696beffa5d2","html_url":"https://github.com/pfnet/image-pull-secrets-provisioner","commit_stats":null,"previous_names":["pfnet/image-pull-secrets-provisioner"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfnet%2Fimage-pull-secrets-provisioner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfnet%2Fimage-pull-secrets-provisioner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfnet%2Fimage-pull-secrets-provisioner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfnet%2Fimage-pull-secrets-provisioner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pfnet","download_url":"https://codeload.github.com/pfnet/image-pull-secrets-provisioner/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252629310,"owners_count":21779192,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T17:06:06.399Z","updated_at":"2025-05-06T05:32:22.830Z","avatar_url":"https://github.com/pfnet.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Image pull secrets provisioner\n\nImage pull secrets provisioner is a Kubernetes controller that provisions image pull secrets for container image registries to any Kubernetes cluster.\n\nThe controller creates and refreshes short-lived credentials for container registries through identity federation, and tailor them to be available as image pull secrets.\n\n## How it works\n\n![Overview](./docs/overview.png)\n\nImage pull secrets provisioner watches Kubernetes ServiceAccounts and performs the following operations.\n\n1. Creates a ServiceAccount's token\n    - The token is a signed JWT\n2. Exchanges the ServiceAccount token with short-lived access token for a container registry through identity federation\n    - The container registry provider verifies the identity and validity of the ServiceAccount token\n3. Creates or updates an image pull secret that contains the access token,\n   and adds it to the ServiceAccount's `.imagePullSecrets` field\n    - Pods using the ServiceAccount will be able to pull container images using the image pull secret\n\n## Supported container image registries\n\nCurrently, image pull secrets provisioner supports the following container registries.\n\n- [Amazon ECR](https://aws.amazon.com/ecr/)\n- [Google Artifact Registry](https://cloud.google.com/artifact-registry)\n\n## Prerequisites\n\nImage pull secrets provisioner presents Kubernetes ServiceAccount tokens (signed JWT) to container registry providers, and then providers verify ServiceAccount tokens following OIDC protocol.\nThe following configuration is required to enable container registry providers to verify ServiceAccount tokens.\n\n- Configure your Kubernetes cluster as an OpenID provider\n    - See [Configure Service Accounts for Pods | Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-issuer-discovery) for details\n- Create OIDC provider for your Kubernetes cluster in your container registry provider\n    - See each container registry provider documentation for details\n        - [Creating OpenID Connect (OIDC) identity providers - AWS Identity and Access Management](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html)\n        - [Configure workload identity federation with Kubernetes | IAM Documentation | Google Cloud](https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes#create_the_workload_identity_pool_and_provider)\n    - See also [Example Terraform configuration for identity federation](#example-terraform-configuration-for-identity-federation).\n\n## Installation\n\nYou can use a Kustomize app in [`config/default`](./config/default/) directory.\n\nYou need to allow the image pull secrets provisoner's ServiceAccount (defined in [`config/rbac/service_account.yaml`](./config/rbac/service_account.yaml))\nto create tokens for your ServiceAccounts.\nYou can create a ClusterRole like the following and bind it to the provisioner ServiceAccount.\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: tokenrequest\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - serviceaccounts/token\n  verbs:\n  - create\n```\n\n## How to use\n\n1. Configure identity federation between a Kubernetes ServiceAccount and a container registry provider\n    - See each provider documentation for details\n        - [Identity providers and federation - AWS Identity and Access Management](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html)\n        - [Configure workload identity federation with Kubernetes | IAM Documentation | Google Cloud](https://cloud.google.com/iam/docs/workload-identity-federation-with-kubernetes)\n    - See also [Example Terraform configuration for identity federation](#example-terraform-configuration-for-identity-federation).\n2. Annotate the ServiceAccount with the configuration for image pull secret provisioning\n    - Amazon ECR:\n      ```yaml\n      apiVersion: v1\n      kind: ServiceAccount\n      metadata:\n        namespace: NAMESPACE\n        name: SERVICE-ACCOUNT-NAME\n        annotations:\n          # Registry to which a provisioned image pull secret authenticates\n          imagepullsecrets.preferred.jp/registry: 999999999999.dkr.ecr.LOCATION.amazonaws.com\n          # Audience value expected by the trust policy for the identity federation\n          imagepullsecrets.preferred.jp/audience: sts.amazonaws.com\n          # ARN of an IAM role that the ServiceAccount will assume\n          imagepullsecrets.preferred.jp/aws-role-arn: arn:aws:iam::999999999999:role/ROLE-NAME\n      ```\n    - Google Artifact Registry:\n      ```yaml\n      apiVersion: v1\n      kind: ServiceAccount\n      metadata:\n        namespace: NAMESPACE\n        name: SERVICE-ACCOUNT-NAME\n        annotations:\n          # Registry to which a provisioned image pull secret authenticates\n          imagepullsecrets.preferred.jp/registry: LOCATION-docker.pkg.dev\n          # Audience value expected by the workload identity provider\n          imagepullsecrets.preferred.jp/audience: //iam.googleapis.com/projects/999999999999/locations/global/workloadIdentityPools/POOL-NAME/providers/PROVIDER-NAME\n          # Full resource name of the workload identity provider\n          imagepullsecrets.preferred.jp/googlecloud-workload-identity-provider: projects/999999999999/locations/global/workloadIdentityPools/POOL-NAME/providers/PROVIDER-NAME\n          # Email address of the Google service account to which the Kubernetes ServiceAccount will impersonate\n          imagepullsecrets.preferred.jp/googlecloud-service-account-email: SERVICE-ACCOUNT-ID@PROJECT-NAME.iam.gserviceaccount.com\n      ```\n3. Use the ServiceAccount for a pod by setting pod's `.spec.serviceAccountName` field\n   ```yaml\n   apiVersion: v1\n   kind: Pod\n   metadata:\n     name: POD-NAME\n   spec:\n     serviceAccountName: SERVICE-ACCOUNT-NAME\n   ...\n   ```\n   See also [Configure Service Accounts for Pods | Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)\n4. The pod will be able to pull container images from the registry\n\n## Image pull secret name\n\nBy default, image pull secrets provisioner creates an image pull secret with the name `imagepullsecret-SERVICE-ACCOUNT-NAME`.\nIf you want to use a different name, you can specify it in the ServiceAccount's annotation.\n\n```yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  namespace: NAMESPACE\n  name: SERVICE-ACCOUNT-NAME\n  annotations:\n    imagepullsecrets.preferred.jp/secret-name: SECRET-NAME\n```\n\n## Pod eviction\n\nImage pull secrets added to a ServiceAccount's `.imagePullSecrets` field do *not* apply to existing pods using the ServiceAccount.\nPods can be stuck in container image pull failures if they are created before an image pull secret is provisioned for their ServiceAccounts.\nTo recover from this situation, image pull secrets provisioner evicts pods that are failing to pull images because they do not have an image pull secret provisioned for their ServiceAccount.\n\nThis behavior can be disabled by passing `--disable-pod-eviction` command line flag.\n\n## Troubleshooting\n\n### Image pull secret is not provisioned\n\nImage pull secrets provisioner emits Kubernetes events for ServiceAccounts when it succeeds or fails to provision image pull secrets.\nInspect a ServiceAccount's events through `kubectl describe serviceaccount NAME` and try to find out what is wrong.\n\n## Appendix\n\n### Example Terraform configuration for identity federation\n\n\u003cdetails\u003e\n\u003csummary\u003eAmazon ECR\u003c/summary\u003e\n\u003cp\u003e\n\n```terraform\nlocals {\n  issuer = \"ISSUER-DOMAIN\"\n  sub    = \"system:serviceaccount:NAMESPACE:NAME\"\n}\n\n# Create an OIDC provider for your Kubernetes cluster.\ndata \"tls_certificate\" \"provider\" {\n  url = \"https://${local.issuer}\"\n}\n\nresource \"aws_iam_openid_connect_provider\" \"provider\" {\n  url             = \"https://${local.issuer}\"\n  client_id_list  = [\"sts.amazonaws.com\"] # Audience value expected by this provider.\n  thumbprint_list = [data.tls_certificate.provider.certificates[0].sha1_fingerprint]\n}\n\n# Allow your Kubernetes ServiceAccount to assume an AWS IAM role.\n# The role has permission to get ECR authorization tokens.\ndata \"aws_iam_policy_document\" \"assume_role_policy\" {\n  statement {\n    effect = \"Allow\"\n    principals {\n      type        = \"Federated\"\n      identifiers = [aws_iam_openid_connect_provider.provider.arn]\n    }\n    actions = [\"sts:AssumeRoleWithWebIdentity\"]\n\n    condition {\n      test     = \"StringEquals\"\n      variable = \"${local.issuer}:aud\"\n      values   = [\"sts.amazonaws.com\"]\n    }\n\n    condition {\n      test     = \"StringEquals\"\n      variable = \"${local.issuer}:sub\"\n      values   = [local.sub]\n    }\n  }\n}\n\ndata \"aws_iam_policy_document\" \"ecr_get_authorization_token_policy\" {\n  statement {\n    effect = \"Allow\"\n    actions = [\n      \"ecr:GetAuthorizationToken\",\n    ]\n    resources = [\"*\"]\n  }\n}\n\nresource \"aws_iam_role\" \"federated\" {\n  name               = \"ROLE-NAME\"\n  assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json\n  inline_policy {\n    name   = \"ECRGetAuthorizationToken\"\n    policy = data.aws_iam_policy_document.ecr_get_authorization_token_policy.json\n  }\n}\n\n# Create an ECR repository and allow the role to pull container images from it.\nresource \"aws_ecr_repository\" \"repository\" {\n  name = \"REPOSITORY-NAME\"\n}\n\ndata \"aws_iam_policy_document\" \"repository_policy\" {\n  statement {\n    effect = \"Allow\"\n    principals {\n      type        = \"AWS\"\n      identifiers = [aws_iam_role.federated.arn]\n    }\n    actions = [\n      \"ecr:BatchGetImage\",\n      \"ecr:GetDownloadUrlForLayer\",\n    ]\n  }\n}\n\nresource \"aws_ecr_repository_policy\" \"policy\" {\n  repository = aws_ecr_repository.repository.name\n  policy     = data.aws_iam_policy_document.repository_policy.json\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGoogle Artifact Registry\u003c/summary\u003e\n\u003cp\u003e\n\n```terraform\nlocals {\n  issuer = \"ISSUER-DOMAIN\"\n  sub    = \"system:serviceaccount:NAMESPACE:NAME\"\n}\n\n# Create a workload identity pool and provider for your Kubernetes cluster.\nresource \"google_iam_workload_identity_pool\" \"pool\" {\n  workload_identity_pool_id = \"POOL-NAME\"\n}\n\nresource \"google_iam_workload_identity_pool_provider\" \"provider\" {\n  workload_identity_pool_provider_id = \"PROVIDER-NAME\"\n  workload_identity_pool_id          = google_iam_workload_identity_pool.pool.workload_identity_pool_id\n  attribute_mapping = {\n    \"google.subject\" = \"\\\"${local.issuer}::\\\" + assertion.sub\"\n  }\n  oidc {\n    issuer_uri = \"https://${local.issuer}\"\n  }\n}\n\n# Allow your Kubernetes ServiceAccount to impersonate a Google service account.\nresource \"google_service_account\" \"sa\" {\n  account_id = \"SERVICE-ACCOUNT-ID\"\n}\n\nresource \"google_service_account_iam_member\" \"federated\" {\n  service_account_id = google_service_account.sa.id\n  role               = \"roles/iam.workloadIdentityUser\"\n  member = join(\"/\", [\n    \"principal://iam.googleapis.com/projects/PROJECT-ID/locations/global\",\n    \"workloadIdentityPools/${google_iam_workload_identity_pool.pool.workload_identity_pool_id}\",\n    \"subject/${local.issuer}::${local.sub}\",\n  ])\n}\n\n# Create a Artifact Registry repository and allow the Google service account to pull container images from it.\nresource \"google_artifact_registry_repository\" \"repository\" {\n  location      = \"LOCATION\"\n  repository_id = \"REPOSITORY-NAME\"\n  format        = \"DOCKER\"\n}\n\nresource \"google_artifact_registry_repository_iam_member\" \"repository_iam_member\" {\n  location   = google_artifact_registry_repository.repository.location\n  repository = google_artifact_registry_repository.repository.name\n  role       = \"roles/artifactregistry.reader\"\n  member     = google_service_account.sa.member\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfnet%2Fimage-pull-secrets-provisioner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpfnet%2Fimage-pull-secrets-provisioner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfnet%2Fimage-pull-secrets-provisioner/lists"}