| .devcontainer | ||
| .sonarqube | ||
| .vscode | ||
| Auth | ||
| Configuration | ||
| docker/odbc | ||
| drivers | ||
| Endpoints | ||
| Infrastructure | ||
| k8s | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| appsettings.json | ||
| AS400API.csproj | ||
| AS400API.sln | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Program.cs | ||
| README.md | ||
AS400API (.NET 9 + ODBC + Dev Container)
Quick start
- Put IBM i Access ODBC RPM into
drivers/and rename it to end with.rpm.disabled(e.g.ibm-iaccess-1.1.x.x86_64.rpm.disabled). The build converts it back to.rpmbut the suffix prevents Apple Silicon devcontainer scaffolding from trying to install the amd64-only driver. - Build & run:
docker compose up --build
VS Code / F5
- Launch profile
AS400APIrunsdotnet runwith hot reload-ready JWT setup.
Environment
- Uses
System.Data.Odbc - Driver name:
IBM i Access ODBC Driver(from ACS). AdjustAS400_DRIVER_NAMEif your driver name differs. - Credentials are passed via env vars in
docker-compose.yml.
Authentication & Authorization
POST /api/auth/login(anonymous) → request body{ "username": "admin", "password": "Pass@123" }.- Demo identities live in-memory so you can plug in real IdP/Keycloak later.
- Default accounts:
admin/Pass@123→ roles:Admin,Operatoroperator/Pass@123→ role:Operator
- Copy the
accessTokenfrom the response and send it as:Authorization: Bearer <token>. - Override JWT issuer/audience/secret via
appsettings.jsonor environment variables (Jwt__Key, etc.).
Endpoints (role scoped)
GET /api/v1/health→ anonymous AS/400 ping viaSYSIBM.SYSDUMMY1GET /api/v1/users/me→ requires any authenticated user; echoes claimsGET /api/v1/as400/databases→ requiresOperatororAdminGET /api/v1/as400/query?sql=...→ requiresAdminGET /api/v1/as400/tables?libraryName=LIB→ requiresOperatororAdminGET /api/v1/as400/table-structure?libraryName=LIB&tableName=TBL→ requiresOperatororAdmin
Logging
- Serilog writes rolling files by default to
Logs/as400-api-.log(configurable inappsettings.json:Serilog:WriteTo:0:Args:path). - Override at runtime with environment variables, e.g.
Serilog__WriteTo__0__Args__path=/var/log/as400/api-.log. - Request logging middleware is enabled; application-specific events (query counts, failures, etc.) are captured with structured properties to aid analysis.
SonarQube analysis
- Install or provision a SonarQube/SonarCloud server and generate a project token.
- Set environment variables (
SONAR_HOST_URL,SONAR_TOKEN, optionallySONAR_PROJECT_KEY,SONAR_PROJECT_NAME; defaults areas400api/AS400API, plusSONAR_ORGANIZATIONfor SonarCloud). - Run
scripts/run-sonar.sh; the script builds the solution, runs tests with Coverlet coverage (when*Tests.csprojprojects exist), and publishes results. - Provide branch and pull request details with
SONAR_BRANCH_NAME,SONAR_PULL_REQUEST_KEY,SONAR_PULL_REQUEST_BRANCH, andSONAR_PULL_REQUEST_BASEwhen needed.
Notes
- On first build, if no RPM exists in
drivers/, the image will build but ODBC won't work until you add the RPM and rebuild.
Kubernetes deployment
Use the manifests in k8s/ when running the API on Kubernetes.
- Create a secret with the AS/400 password (and optional JWT key) so it stays separate from the rest of the configuration:
Alternatively create the secret imperatively:cp k8s/secret-example.yaml k8s/secret.yaml # edit k8s/secret.yaml and set real values kubectl apply -f k8s/secret.yamlkubectl create secret generic as400api-secrets --from-literal=AS400_PASSWORD=... --from-literal=JWT__KEY=.... - Apply the non-sensitive settings:
kubectl apply -f k8s/configmap.yaml - Deploy the workload and service:
kubectl apply -f k8s/deployment.yaml kubectl apply -f k8s/service.yaml
The deployment imports the configuration via envFrom so the password is sourced from the secret while everything else comes from the config map. Update image names, probes, and resource requests to fit your environment.