Files
APAW/.kilo/shared/gitea-auth.md
¨NW¨ 7523911812 fix(security): extricate hardcoded Gitea credentials, add centralized auth module
- Remove all hardcoded NW:eshkink0t credentials from 9 files across skills, commands, rules, and specs
- Add .kilo/shared/gitea-auth.md with get_gitea_token() and .kilo/gitea.jsonc config structure
- All Gitea API callers now use env vars (GITEA_TOKEN → GITEA_USER+GITEA_PASS → ValueError)
- Fix task-analysis/SKILL.md broken functions (orphaned req references, stray parentheses)
- Replace hardcoded UniqueSoft/APAW API URLs with get_target_repo() auto-detection in 3 files
- Update README.md, STRUCTURE.md, AGENTS.md with centralized auth documentation
- Add EVOLUTION_LOG Entry #5 documenting credentials extrication
2026-04-19 11:43:59 +01:00

4.0 KiB

Gitea Auth Module (Shared)

Centralized authentication for Gitea API. NEVER hardcode credentials in agent code.

Auth Resolution Order

1. GITEA_TOKEN env var          → Use directly (PREFERRED)
2. GITEA_USER + GITEA_PASS     → Create temporary token via Basic Auth
3. .env file                   → Read env vars from .env
4. Interactive prompt           → Ask user (last resort)

Configuration

All credentials come from environment variables defined in .kilo/gitea.jsonc:

Env Var Required Description
GITEA_API_URL No API base URL (default: https://git.softuniq.eu/api/v1)
GITEA_TOKEN Preferred Pre-existing API token
GITEA_USER Fallback Username for Basic Auth token creation
GITEA_PASS Fallback Password for Basic Auth token creation
GITEA_TARGET_REPO No Override target project (auto-detected otherwise)

Python Auth Function

import os
import base64
import json
import urllib.request


def get_gitea_config():
    """Load Gitea configuration from env vars. NEVER hardcode credentials."""
    return {
        'api_url': os.environ.get('GITEA_API_URL', 'https://git.softuniq.eu/api/v1'),
        'token': os.environ.get('GITEA_TOKEN', ''),
        'user': os.environ.get('GITEA_USER', ''),
        'pass': os.environ.get('GITEA_PASS', ''),
    }


def get_gitea_token():
    """Get Gitea API token. Prefers GITEA_TOKEN env var.
    Falls back to creating token via Basic Auth from GITEA_USER/GITEA_PASS.
    Raises ValueError if no credentials available."""
    config = get_gitea_config()

    # 1. Use existing token (preferred)
    if config['token']:
        return config['token']

    # 2. Create token via Basic Auth (fallback)
    user = config['user']
    password = config['pass']  # Note: 'pass' is reserved word, use config['pass']

    if not user or not password:
        raise ValueError(
            'Gitea auth required. Set GITEA_TOKEN or GITEA_USER+GITEA_PASS env vars. '
            'Create .env file with: GITEA_TOKEN=your-token'
        )

    credentials = base64.b64encode(f"{user}:{password}".encode()).decode()
    req = urllib.request.Request(
        f"{config['api_url']}/users/{user}/tokens",
        data=json.dumps({"name": f"agent-{os.getpid()}", "scopes": ["all"]}).encode(),
        headers={
            'Content-Type': 'application/json',
            'Authorization': f'Basic {credentials}',
        },
        method='POST',
    )
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())['sha1']

Bash Auth Function

# Get Gitea token — prefers GITEA_TOKEN, falls back to Basic Auth
get_gitea_token() {
  if [ -n "$GITEA_TOKEN" ]; then
    echo "$GITEA_TOKEN"
    return
  fi

  if [ -z "$GITEA_USER" ] || [ -z "$GITEA_PASS" ]; then
    echo "ERROR: Set GITEA_TOKEN or GITEA_USER+GITEA_PASS" >&2
    return 1
  fi

  local API_URL="${GITEA_API_URL:-https://git.softuniq.eu/api/v1}"
  local CRED=$(echo -n "$GITEA_USER:$GITEA_PASS" | base64)

  curl -s -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Basic $CRED" \
    -d '{"name":"agent-token","scopes":["all"]}' \
    "$API_URL/users/$GITEA_USER/tokens" | jq -r '.sha1 // empty'
}

.env File Template

# Gitea Integration (NEVER commit this file)
GITEA_API_URL=https://git.softuniq.eu/api/v1
GITEA_TOKEN=your-api-token-here
# Fallback (only if no token):
# GITEA_USER=your-username
# GITEA_PASS=your-password
# GITEA_TARGET_REPO=Owner/RepoName

CRITICAL RULES

  1. NEVER hardcode credentials — no username = "NW" or password = "eshkink0t" in any file
  2. NEVER commit .env — it's in .gitignore
  3. ALWAYS prefer GITEA_TOKEN — tokens are scoped and revocable
  4. Fallback uses env varsGITEA_USER + GITEA_PASS, not hardcoded strings
  5. Raise error if no creds — don't silently fail, tell user to set env vars
  6. Use this module — all Gitea API calls should use get_gitea_token() from here