{"id":21355210,"url":"https://github.com/jlucaspains/go-rest-template","last_synced_at":"2025-04-09T12:07:59.732Z","repository":{"id":159893287,"uuid":"625414779","full_name":"jlucaspains/go-rest-template","owner":"jlucaspains","description":"Golang REST API Template","archived":false,"fork":false,"pushed_at":"2025-04-01T17:17:46.000Z","size":298,"stargazers_count":83,"open_issues_count":7,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-02T10:14:53.910Z","etag":null,"topics":["docker","docker-compose","golang","jwt-auth","kubernetes","open-policy-agent","rest-api","template"],"latest_commit_sha":null,"homepage":"","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/jlucaspains.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"jlucaspains","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2023-04-09T03:13:19.000Z","updated_at":"2025-03-27T12:58:24.000Z","dependencies_parsed_at":"2023-11-07T03:10:15.777Z","dependency_job_id":"658c2097-1e38-46a3-964d-d9faf9884b97","html_url":"https://github.com/jlucaspains/go-rest-template","commit_stats":{"total_commits":110,"total_committers":2,"mean_commits":55.0,"dds":0.4363636363636364,"last_synced_commit":"218872afee889cc674a62a1f0b9567ec860e9500"},"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlucaspains%2Fgo-rest-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlucaspains%2Fgo-rest-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlucaspains%2Fgo-rest-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jlucaspains%2Fgo-rest-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jlucaspains","download_url":"https://codeload.github.com/jlucaspains/go-rest-template/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248036067,"owners_count":21037092,"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":["docker","docker-compose","golang","jwt-auth","kubernetes","open-policy-agent","rest-api","template"],"created_at":"2024-11-22T04:16:04.294Z","updated_at":"2025-04-09T12:07:59.709Z","avatar_url":"https://github.com/jlucaspains.png","language":"Go","funding_links":["https://ko-fi.com/jlucaspains"],"categories":[],"sub_categories":[],"readme":"## Features\n- [x] Golang\n  - [x] VS Code extension recommendations\n- [x] REST API\n  - [x] Handlers with dependency injection\n  - [x] Default Health handler with DB ping check\n  - [x] Swagger UI\n  - [x] Swagger json generation with `swag init`\n  - [x] Config from .env or environment variables\n- [x] Auth\n  - [x] Authentication with OAuth2 and JWT tokens\n  - [x] Use .well-known/openid-configuration for configuration agnostic of provider\n  - [x] Authorization via Open Policy Agent (OPA) policies\n- [x] DB\n  - ~~[x] GORM~~\n  - [x] SQLC\n  - [x] Automatic Migrations\n  - [x] Postgres DB provider\n  - ~~[x] SQLite DB provider~~\n- [x] CI/CD\n  - [x] Dockerfile\n  - [x] Docker compose\n  - [x] Kubernetes\n  - [x] Github actions workflow\n\n## How to use this template\nThis is a template repository so you can create a new repository based on this one. See instructions [here](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template).\n\n## Getting started Locally\nYou should use the latest version available of Go. The current version used by this repository is 1.20.\n\n### Install Go dependencies\n```cmd\ngo mod download\n```\n\n### ENV\n\u003e **IMPORTANT**: You should replace `AUTH_CONFIG_URL` and `AUTH_AUDIENCE` value with actual values from an OpenID provider.\n\nCreate a .env file in the root of the project with the following configs:\n\n```env\nENV=local\nWEB_PORT=localhost:8000\nAUTH_CONFIG_URL=https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/v2.0/.well-known/openid-configuration\nAUTH_AUDIENCE=api://c571ab3c-0fde-43b2-b010-77e7bdd0d6f7/api/\nENABLE_SWAGGER=true\nDB_CONNECTION_STRING=postgres://postgres:94235CXcx@localhost:5432/goapitemplate?sslmode=disable\n```\nBy default, the template uses Postres and thus you need it installed locally or available elsewhere.\n\n### Run\n```powershell\ngo run .\\main.go\n```\n\nThe API should now be available at http://localhost:8000/swagger/index.html\n\n### Test\nWithout test coverage:\n```powershell\ngo test ./...\n```\n\nWith HTML coverage output:\n```powershell\ngo test -coverprofile=coverage ./...\ngo tool cover -html=coverage\n```\n\n### Build\n```powershell\ngo build\n```\nIn Windows, the command above yields a executable file `go-rest-template.exe`. In Linux, it yields an executable of same name but without extension.\n\n## Deploy\n### Docker\n\u003e **IMPORTANT**: You should replace `AUTH_CONFIG_URL` and `AUTH_AUDIENCE` value with actual values from an OpenID provider.\n\n\u003e **NOTE**: You will need docker installed and running\n\nFirst set the `AUTH_CONFIG_URL`, `AUTH_AUDIENCE`, and `POSTGRES_PASSWORD` environment variables.\n\nOn Windows using PowerShell:\n```powershell\n$env:AUTH_CONFIG_URL = \"https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/v2.0/.well-known/openid-configuration\"\n$env:AUTH_AUDIENCE = \"api://00000000-0000-0000-0000-000000000000/api/\"\n$env:POSTGRES_PASSWORD = \"mysecretpassword\"\n```\n\nOn Linux using bash:\n```bash\nexport AUTH_CONFIG_URL=\"https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/v2.0/.well-known/openid-configuration\"\nexport AUTH_AUDIENCE=\"api://00000000-0000-0000-0000-000000000000/api/\"\nexport POSTGRES_PASSWORD=\"mysecretpassword\"\n```\n\nThen, run docker compose:\n```powershell\ndocker compose up -d\n```\n\n### Kubernetes\nYou may use [minikube](https://minikube.sigs.k8s.io/docs/start/) locally to test kubernetes configuration.\n\n```bash\nkubectl create secret generic app-secrets --from-literal=AUTH_CONFIG_URL=\u003curl\u003e --from-literal=AUTH_AUDIENCE=\u003caudience\u003e --from-literal=DB_CONNECTION_STRING=\u003cconnection string\u003e\n\nkubectl create secret generic db-secrets --from-literal=POSTGRES_DB=\u003cdb name\u003e --from-literal=POSTGRES_USER=\u003cdb user\u003e --from-literal=POSTGRES_PASSWORD=\u003cpassword\u003e\n\nkubectl apply -f ./db-pvc.yaml\nkubectl apply -f ./db-pv.yaml\nkubectl apply -f ./db-deployment.yaml\nkubectl apply -f ./db-service.yaml\nkubectl apply -f ./app-configmap.yaml\nkubectl apply -f ./app-deployment.yaml\nkubectl apply -f ./app-service.yaml\n```\n\n## Authentication\nOn startup, the application will execute an HTTP GET over the URL stored in `AUTH_CONFIG_URL` configuration. This variable should be a `.well-known/openid-configuration` endpoint which is typically provided by OAuth2 or OpenId providers such as:\n\n|Provider|URL|Notes|\n|-|-|-|\n|Azure|https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/v2.0/.well-known/openid-configuration|The URL changes according to your Azure AD tenant id|\n|Google|https://accounts.google.com/.well-known/openid-configuration||\n|Facebook|https://www.facebook.com/.well-known/openid-configuration/||\n\nThe startup will automatically pull the issuer, jwks, and token signing algorithm. These fields are used to validate the JWT token. The jwks is also monitored for changes and is updated as needed. \n\nAdditionally, the JWT is validated against the configured `AUTH_AUDIENCE` so only tokens intended for this API are accepted. The `AUTH_CLAIMS` configuration is used in order to lookup and add claims from the JWT body to the provided User interface so the app is aware of information such as user name, email, etc.\n\nThe authentication middleware will validate the JWT against the parameters set and allow (or not) the API pipeline to proceed. Any additional validation should be executed by the Authorization layer.\n\n## Authorization\nAuthorization is provided via OPA policy with input fields method, path, and token. You may modify the `OpaMiddleware` to add more fields as necessary. The following basic policy is provided:\n\n```opa\npackage authz\n\nimport future.keywords.if\n\ndefault allow = false\n\nallow if {\n\tendswith(payload.email, \"@gmail.com\")\n\tpayload.verified\n\tstartswith(input.path, \"/person\")\n}\n\npayload := {\"verified\": verified, \"email\": payload.email} if {\n\t[_, payload, _] := io.jwt.decode(input.token)\n\tverified := true\n}\n```\n\nNote that the token input field is the full JWT provided by the consumer. You may decode it and use any of the provided fields such as Role, name, email, etc to validate whether the call is authorized or not.\n\nThe above basic policy enforces that the URL path must start with `/person` and the user email must end with `@gmail.com`. This is obviously just to get the authorization started and should be modified before using this template. For more information on OPA, please see https://www.openpolicyagent.org/.\n\nThe `OpaMiddleware` is a combined local PEP (Policy Enforcement Point) and PDP (Policy Decision Point). As such, any time your policy changes, you need a code change as the policy is stored locally, and a release. As your needs outgrow this approach, you should look into introducing a centralized PDP, adding a PIP (Policy Information Point) to enrich the policy inputs, and PAP (Policy Administration point) to create or modify policies without the need for a release.\n\n## CI/CD\nBy default, this repository includes a single GitHub Actions workflow with 3 jobs that will:\n\n1. Prepare and validate go code\n2. Execute unit tests\n3. Execute Linter\n4. Determine Semver by using git commits\n   1. See https://gitversion.net/docs/\n5. Build, tag, and push docker image to docker hub\n   1. You may want to change this step and push to a private repository\n6. Deploy to Azure Kubernetes Service\n7. Deploy to Azure Web App\n\n## General recommendations\nBefore you push a similar solution to a production environment, keep the following recommendations in mind:\n\n1. Kubernetes secrets are not really secret. If possible, you should leverage a secrets platform such as Azure Key Vault.\n2. Favor managed database solutions instead of container based solution. Remember that if you use database in a container, you will need to take care of backups and other reliability related features that are typically available in managed solutions in cloud platforms such as AWS and Azure.\n3. Avoid using the latest tag for releases. If a pod goes down and comes back up, it might use a different version of the image than the other containers of the same type.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjlucaspains%2Fgo-rest-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjlucaspains%2Fgo-rest-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjlucaspains%2Fgo-rest-template/lists"}