@echo off
setlocal

REM created by CVI
echo =========================================================================================
echo = v1_2024  ---  This Script is designed to be used for generating csr and key           =
echo =        for the Domain CA sign it and create CRT P12 and JKS                           =
echo =        it contains full certificate config including Subject Alternative Name(s)      =
echo =========================================================================================
REM ===========================================
REM set the directory paths
REM ===========================================
set "PROJECT_DIR=%~dp0"
set "PROJECT_DIR=%PROJECT_DIR:~0,-1%"
set "TOOLS_DIR=%PROJECT_DIR%\tools"
set "OPENSSL_DIR=%TOOLS_DIR%\openssl\x64\bin"
set "CERTS_DIR=%TOOLS_DIR%\certs"
set "KEYTOOL_DIR=%TOOLS_DIR%\jdk\bin"
set "OPENSSL_CONF=%TOOLS_DIR%\openssl\ssl\openssl.cnf"

REM ===========================================
REM Add here the certificate template name
REM ===========================================
set "CertificateTemplate=ABSWebserverCertificateTemplate"

REM ===========================================================================
REM Add here the requested parameters
REM ===========================================================================
set "COUNTRY=CA"                  ::  Add here the Country 2 Letters
set "ORG=Ecotex"                 ::  Company initials 
set "ORG_UNIT=IT"                 ::  Department e.g. IT
set "ROOT_CA=ECOTEX-Root-CA"     ::  Add here the Root CA name

REM ===========================================================================

echo Current Project Directory: %PROJECT_DIR%
echo Tools Directory: %TOOLS_DIR%
echo OpenSSL Directory: %OPENSSL_DIR%

REM Ensure the certs directory exists
if not exist "%CERTS_DIR%" (
    mkdir "%CERTS_DIR%"
    echo %CERTS_DIR% created
) else (
    echo %CERTS_DIR% already exists
)

REM Check if workstation name is passed as argument
if "%1"=="" goto NoArg
set "DOMAIN_NAME=%1"
goto Continue

:NoArg
echo No workstation name provided as argument.
set /p DOMAIN_NAME=Please enter the domain name (e.g., abssolute.net): 
if "%DOMAIN_NAME%"=="" (
    echo No workstation name provided. Exiting.
    exit /b 1
)

:Continue
REM Display workstation name
echo Workstation and Domain Name: %DOMAIN_NAME%

REM Extract the first local IP address
for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /r /c:"IPv4.*"') do (
    for /f "tokens=1 delims= " %%b in ("%%a") do (
        set "LOCAL_IP=%%b"
        goto :break
    )
)
:break

REM Display IP address
echo Local IP: %LOCAL_IP%

REM Define file names
echo Setting file names...
set "KEY_FILE=%CERTS_DIR%\%DOMAIN_NAME%.key"
set "CSR_FILE=%CERTS_DIR%\%DOMAIN_NAME%.csr"
set "CRT_FILE=%CERTS_DIR%\%DOMAIN_NAME%.crt"
set "P12_FILE=%CERTS_DIR%\%DOMAIN_NAME%.p12"
set "JKS_FILE=%CERTS_DIR%\%DOMAIN_NAME%.jks"
set "RSP_FILE=%CERTS_DIR%\%DOMAIN_NAME%.rsp"
set "PASSWD=changeit"                         :: You can modify this password if needed
set "CA_CERT=%TOOLS_DIR%\certs\ca-cert.pem"  :: Specify path to CA certificate if required

REM Define Subject Alternative Name(s)
echo Setting SAN...
set "SAN=DNS:%DOMAIN_NAME%,DNS:www.%DOMAIN_NAME%,IP:%LOCAL_IP%"
echo SAN: %SAN%

set OPENSSL_CONF=%CERTS_DIR%\openssl-san.cnf

REM ===========================================
REM Clean up existing certifiates for the %DOMAIN_NAME%
REM ===========================================
del "%OPENSSL_CONF%"
del "%KEY_FILE%"
del "%CSR_FILE%"
del "%CRT_FILE%"
del "%P12_FILE%"
del "%JKS_FILE%"
del "%RSP_FILE%"

REM ===========================================
REM Step 1: Create the OpenSSL config file with SAN dynamically
REM ===========================================
echo Creating OpenSSL config file...
(
    echo [ req ]
    echo default_md = sha256
    echo prompt = no
    echo distinguished_name = req_distinguished_name
    echo req_extensions = v3_req
	echo [ req_distinguished_name ]
	echo commonName = *.%DOMAIN_NAME%
    echo stateOrProvinceName = N/A
    echo localityName = N/A
	echo countryName = %COUNTRY% 
    echo organizationName = %ORG% 
    echo organizationalUnitName = %ORG_UNIT%
    echo [ v3_req ]
    echo keyUsage = critical, digitalSignature, keyEncipherment
    echo extendedKeyUsage = serverAuth
    echo subjectAltName = @alt_names
	echo [ alt_names ]
    echo DNS.1 = *.%DOMAIN_NAME%
    echo DNS.2 = localhost
    echo IP.1 = 127.0.0.1
) >  "%OPENSSL_CONF%"

echo OpenSSL config file creation attempted to be placed %OPENSSL_CONF%.

REM Verify the OpenSSL config file was created
if not exist "%CERTS_DIR%\openssl-san.cnf" (
    echo OpenSSL config file was not created. Exiting.
    exit /b 1
) else (
    echo OpenSSL config file created successfully.
)

REM ===========================================
REM Step 2: Generate the Private Key (.key) and CSR (.csr)
REM ===========================================
echo Generating Private Key ("%KEY_FILE%") and CSR ("%CSR_FILE%")...
"%OPENSSL_DIR%\openssl.exe" req -new -newkey rsa:2048 -nodes -keyout "%KEY_FILE%" -out "%CSR_FILE%" -config "%CERTS_DIR%\openssl-san.cnf" || goto Error

REM ===========================================
REM Step 3: Sign the CSR with our own Root CA
REM ===========================================

REM Root CA key and cert
set "CA_KEY=%TOOLS_DIR%\certs\ca-key.pem"
set "CA_CERT=%TOOLS_DIR%\certs\ca-cert.pem"
set "CA_SERIAL=%TOOLS_DIR%\certs\ca-serial.srl"

REM Create CA if missing
if not exist "%CA_KEY%" (
    echo Creating Root CA key and certificate...
    "%OPENSSL_DIR%\openssl.exe" genrsa -out "%CA_KEY%" 4096
    "%OPENSSL_DIR%\openssl.exe" req -x509 -new -nodes -key "%CA_KEY%" ^
        -sha256 -days 3650 -out "%CA_CERT%" ^
        -subj "/C=%COUNTRY%/O=%ORG%/OU=%ORG_UNIT%/CN=%ROOT_CA%"
)

REM Sign the CSR with the CA
echo Signing CSR with Root CA...
"%OPENSSL_DIR%\openssl.exe" x509 -req -in "%CSR_FILE%" ^
    -CA "%CA_CERT%" -CAkey "%CA_KEY%" -CAcreateserial -out "%CRT_FILE%" ^
    -days 1095 -sha256 -extfile "%CERTS_DIR%\openssl-san.cnf" -extensions v3_req || goto Error

REM "%OPENSSL_DIR%\openssl.exe" x509 -req -days 730 -in "%CSR_FILE%" -signkey "%KEY_FILE%" -out "%CRT_FILE%" || goto Error
REM certreq -submit -attrib "CertificateTemplate:%CertificateTemplate%" "%CSR_FILE%" "%CRT_FILE%" || goto Error

REM ===========================================
REM Step 4: Convert the .crt and .key to .p12 (PKCS12 format)
REM ===========================================
echo Converting to PKCS12 format ("%P12_FILE%")...
set "BUNDLE_FILE=%CERTS_DIR%\%DOMAIN_NAME%-bundle.crt"
copy /b "%CRT_FILE%" + "%CA_CERT%" "%BUNDLE_FILE%" >nul

"%OPENSSL_DIR%\openssl.exe" pkcs12 -export -in "%CRT_FILE%" -inkey "%KEY_FILE%" ^
    -out "%P12_FILE%" -name "%DOMAIN_NAME%" -certfile "%CA_CERT%" ^
    -password pass:"%PASSWD%" || goto Error
REM "%OPENSSL_DIR%\openssl.exe" pkcs12 -export -in "%CRT_FILE%" -inkey "%KEY_FILE%" -out "%P12_FILE%" -name "%DOMAIN_NAME%" -CAfile "%CA_CERT%" -caname "root" -password pass:"%PASSWD%" || goto Error

REM ===========================================
REM Step 5: Convert .p12 to .jks (Java Keystore format)
REM ===========================================
echo Converting PKCS12 (.p12) to Java Keystore (.jks) format ("%JKS_FILE%")...
"%KEYTOOL_DIR%\keytool.exe" -importkeystore -srckeystore "%P12_FILE%" -srcstoretype PKCS12 -srcstorepass "%PASSWD%" -destkeystore "%JKS_FILE%" -deststoretype JKS -deststorepass "%PASSWD%" -alias "%DOMAIN_NAME%"

REM Output files location
echo.
echo Certificate and keys have been generated in: "%CERTS_DIR%"
echo Private Key: "%KEY_FILE%"
echo CSR: "%CSR_FILE%"
echo Signed Certificate (CRT): "%CRT_FILE%"
echo PKCS12 File: "%P12_FILE%"
echo Java Keystore (JKS): "%JKS_FILE%"

goto End

:Error
echo An error occurred during the process. Exiting.

:End
endlocal
pause
