{"id":50475994,"url":"https://github.com/dvob/hati","last_synced_at":"2026-06-01T13:03:34.743Z","repository":{"id":352283795,"uuid":"1092466698","full_name":"dvob/hati","owner":"dvob","description":"Harbor Token Issuer","archived":false,"fork":false,"pushed_at":"2025-11-08T17:38:35.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-18T21:07:24.329Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dvob.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-08T17:19:50.000Z","updated_at":"2025-11-08T17:38:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dvob/hati","commit_stats":null,"previous_names":["dvob/hati"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/dvob/hati","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvob%2Fhati","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvob%2Fhati/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvob%2Fhati/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvob%2Fhati/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dvob","download_url":"https://codeload.github.com/dvob/hati/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvob%2Fhati/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33775865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2026-06-01T13:03:33.841Z","updated_at":"2026-06-01T13:03:34.734Z","avatar_url":"https://github.com/dvob.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hati\nThe **HA**arbor **T**oken **I**ssuer allows you to obtain short lived robot account tokens by authenticating using JWT tokens. This allows you to easily access Harbor without the hassle of token management.\n\nEssentially this means that you configure Hati to trust your platform (`-jwks-url`) which could be your Gitlab instance, Github a Kubernetes Cluster, etc. (see examples below).\nThen you obtain a JWT token from your platform which you in turn exchange for a Harbor Robot Account token via a HTTP request.\n\n```\ncurl -X POST -H \"Authorization: Bearer $YOUR_PLATFORM_JWT\" \"https://hati.yourdomain.com/?project=mytest\u0026permission=push\"\n```\n```\n{\n    \"user\": \"robot$mytest+hati-ghjashebhbf\",\n    \"secret\": \"THE_ROBOT_ACCOUNT_TOKEN\"\n}\n```\n\nThen you can login using:\n```\necho $hati_secret | docker login --username $hati_user harbor.yourdomain.com --password-stdin\n```\n\nAuthorization is performed based on the claims in the JWT token and rules written in [CEL](https://cel.dev/) and/or [JavaScript](https://github.com/robertkrimen/otto/blob/master/README.md).\n\nCEL:\n```\nclaims.sub == \"repo:dvob/ci-test:ref:refs/heads/main\"\n```\n\nJavaScript:\n```\nfunction isAuthorized(project, permission, claims) {\n  return claims.sub === \"repo:dvob/ci-test:ref:refs/heads/main\"\n}\n```\n\n# Examples\n\n## Gitlab\n* Example Pipeline: [.gitlab-ci.yml](./examples/gitlab-ci.yml)\n* Example Hati configuration \n  ```\n  hati -jwks-url https://gitlab.com/oauth/discovery/keys \\\n       -harbor-url https://harbor.yourdomain.com \\\n       -harbor-user admin \\\n       -harbor-password Harbor12345\n       -skip-audience-check=true\n       -cel-file=examples/rule-gitlab.cel\n  ```\n* Docs concerning Gitlab id_tokens: https://docs.gitlab.com/ci/secrets/id_token_authentication/\n\nCEL rule to permit specific Gitlab repository:\n```\nclaims.sub == \"project_path:dvob/hati-test:ref_type:branch:ref:main\"\n```\n\n## Github\n* Example Pipeline: [github-workflow.yml](./examples/github-workflow.yml)\n* Example Hati configuration \n  ```\n  hati -jwks-url=https://token.actions.githubusercontent.com/.well-known/jwks \\\n       -harbor-url https://harbor.yourdomain.com \\\n       -harbor-user admin \\\n       -harbor-password Harbor12345\n       -skip-audience-check=true\n       -cel-file=examples/rule-github.cel\n  ```\n* Docs concerning Github OIDC tokens: https://docs.github.com/en/actions/reference/security/oidc#oidc-token-claims\n\nCEL rule to permit specific Github repository:\n```\nclaims.sub == \"repo:dvob/ci-test:ref:refs/heads/main\"\n```\n\n# Deployment\n\nIn the directory manifets you find the manifests to deploy Hati along side a Harbor instance which got installed using the [Harbor Helm Chart](https://github.com/goharbor/harbor-helm).\n\nBefore you can use it you have to configure the follogin things accordingly:\n- set ingress host name (Ingress)\n- configure rules to your needs (ConfigMaps)\n- configure JWSK URL (Deployment)\n\n```\nkubectl -n harbor apply -f manifests/\n```\n\n# Caveats\n\nMinimum lifetime of a robot account is one day. For each successfully authenticated and authorized request we create a new robot account.\nSo if you have many requests you will end up with many many robot accounts.\n\n\nCurrently you need the admin user with password as system robot accounts are not able to create robot accounts due to a bug (https://github.com/goharbor/harbor/issues/21406).\n\n\nAn alternative to Hati would be Hashicorp Vault with a plugin for Harbor: https://github.com/manhtukhang/vault-plugin-harbor\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvob%2Fhati","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdvob%2Fhati","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvob%2Fhati/lists"}