Go to file
2025-10-27 22:59:05 +07:00
.devcontainer Initial Project 2025-10-17 16:01:56 +07:00
.sonarqube Update JK 2025-10-21 11:54:44 +07:00
.vscode Initial Project 2025-10-17 16:01:56 +07:00
AS400API.Tests Update JK, Test configure 2025-10-21 08:09:21 +07:00
Auth Initial Project 2025-10-17 16:01:56 +07:00
Configuration Initial Project 2025-10-17 16:01:56 +07:00
docker/odbc Initial Project 2025-10-17 16:01:56 +07:00
drivers Initial Project 2025-10-17 16:01:56 +07:00
Endpoints Initial Project 2025-10-17 16:01:56 +07:00
Infrastructure Initial Project 2025-10-17 16:01:56 +07:00
k8s Initial Project 2025-10-17 16:01:56 +07:00
scripts Update JK 2025-10-21 11:54:44 +07:00
.dockerignore Initial Project 2025-10-17 16:01:56 +07:00
.gitignore Initial Project 2025-10-17 16:01:56 +07:00
appsettings.json Initial Project 2025-10-17 16:01:56 +07:00
AS400API.csproj JK 2025-10-24 22:04:07 +07:00
AS400API.sln Add test 2025-10-20 14:25:01 +07:00
docker-compose.yml Initial Project 2025-10-17 16:01:56 +07:00
Dockerfile Initial Project 2025-10-17 16:01:56 +07:00
Jenkinsfile JK 2025-10-27 22:59:05 +07:00
Jenkinsfile copy Update Jenkinsfile to local 2025-10-21 00:08:03 +07:00
Jenkinsfile copy 2 New JK 2025-10-27 21:48:23 +07:00
Program.cs JK 2025-10-21 12:32:06 +07:00
README.md JK 2025-10-27 22:03:46 +07:00

AS400API (.NET 9 + ODBC + Dev Container)

Quick start

  1. 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 .rpm but the suffix prevents Apple Silicon devcontainer scaffolding from trying to install the amd64-only driver.
  2. Build & run:
docker compose up --build
  1. Open http://localhost:8080/swagger

VS Code / F5

  • Launch profile AS400API runs dotnet run with hot reload-ready JWT setup.

Environment

  • Uses System.Data.Odbc
  • Driver name: IBM i Access ODBC Driver (from ACS). Adjust AS400_DRIVER_NAME if 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, Operator
    • operator / Pass@123 → role: Operator
  • Copy the accessToken from the response and send it as: Authorization: Bearer <token>.
  • Override JWT issuer/audience/secret via appsettings.json or environment variables (Jwt__Key, etc.).

Endpoints (role scoped)

  • GET /api/v1/health → anonymous AS/400 ping via SYSIBM.SYSDUMMY1
  • GET /api/v1/users/me → requires any authenticated user; echoes claims
  • GET /api/v1/as400/databases → requires Operator or Admin
  • GET /api/v1/as400/query?sql=... → requires Admin
  • GET /api/v1/as400/tables?libraryName=LIB → requires Operator or Admin
  • GET /api/v1/as400/table-structure?libraryName=LIB&tableName=TBL → requires Operator or Admin

Logging

  • Serilog writes rolling files by default to Logs/as400-api-.log (configurable in appsettings.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.

Jenkins CI notes

  • The repo includes a declarative Jenkinsfile that builds on the mcr.microsoft.com/dotnet/sdk:9.0 container image and expects Jenkins parameters for GIT_REPO_URL, GIT_CREDENTIALS_ID, SONARQUBE_SERVER, and SONAR_TOKEN_ID. Create the credentials in Manage Jenkins Credentials before running the job.
  • Set AGENT_LABEL (default docker) to a Jenkins agent that has the Docker CLI available so the pipeline can launch containers.
  • Update the Sonar project key or organization by editing SONAR_PROJECT_KEY / SONAR_ORG in the Jenkins parameter defaults or overriding them per-run; the pipeline passes these values to dotnet-sonarscanner.
  • The pipeline publishes unit-test results, OpenCover XML, and HTML coverage reports; open the “Code Coverage” HTML report in the Jenkins build sidebar or download the archived artifacts artifacts/AS400API-<build>-<commit>/reports/coverage-html/index.html.
  • SCA results (security-reports/nuget-vulnerabilities.txt and optional Dependency-Check HTML) and application logs from Logs/ are archived automatically so you can review findings without re-running the build.

SonarQube analysis

  • Install or provision a SonarQube/SonarCloud server and generate a project token.
  • Set environment variables (SONAR_HOST_URL, SONAR_TOKEN, optionally SONAR_PROJECT_KEY, SONAR_PROJECT_NAME; defaults are as400api / AS400API, plus SONAR_ORGANIZATION for SonarCloud).
  • Run scripts/run-sonar.sh; the script builds the solution, runs tests with Coverlet coverage (when *Tests.csproj projects exist), and publishes results.
  • Provide branch and pull request details with SONAR_BRANCH_NAME, SONAR_PULL_REQUEST_KEY, SONAR_PULL_REQUEST_BRANCH, and SONAR_PULL_REQUEST_BASE when 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.

  1. Create a secret with the AS/400 password (and optional JWT key) so it stays separate from the rest of the configuration:
    cp k8s/secret-example.yaml k8s/secret.yaml
    # edit k8s/secret.yaml and set real values
    kubectl apply -f k8s/secret.yaml
    
    Alternatively create the secret imperatively: kubectl create secret generic as400api-secrets --from-literal=AS400_PASSWORD=... --from-literal=JWT__KEY=....
  2. Apply the non-sensitive settings:
    kubectl apply -f k8s/configmap.yaml
    
  3. 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.