Skip to content

EDFI-2776 Add Windows IIS installation scripts - #2

Merged
analiliagutierrez merged 12 commits into
mainfrom
EDFI-2776_Windows_Install_Scripts
Jul 24, 2026
Merged

EDFI-2776 Add Windows IIS installation scripts#2
analiliagutierrez merged 12 commits into
mainfrom
EDFI-2776_Windows_Install_Scripts

Conversation

@analiliagutierrez

@analiliagutierrez analiliagutierrez commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR imports the windows-install script suite into the dedicated Admin App Installation Scripts repository. The scripts fully automate an end-to-end Windows / IIS installation of the Ed-Fi Admin App (v4.0.1), supporting either SQL Server or a Dockerized PostgreSQL backing store, and Keycloak, Entra ID, or Google Workspace as the OIDC identity provider. TLS is on by default, the API runs under the httpPlatform handler, the app connects with a least-privilege database login and a per-install data-encryption key is generated. The suite was validated end to end against Admin App v4.0.1 across both database engines and all three identity providers before this import.

Ticket

  • EDFI-2776 — Windows + SQL Server installation scripts (primary)
  • Also delivers EDFI-2777 (Windows + PostgreSQL / Docker) and EDFI-2774 (Entra ID OIDC config seeding, validated on both engines)

Type of Change

  • Feature / Script

What Changed

  • windows-install/ — the phased installer and supporting scripts:
    • install-all.ps1 — master installer (three phases: prereqs, build, deploy), fully automated.
    • 00-check-prereqs.ps106-deploy-fe.ps1 — per-section scripts (SQL / IIS / Node prereqs, build, API deploy, FE deploy) that can also be run individually.
    • idp-keycloak-setup.ps1 / idp-keycloak-start.ps1 — local Keycloak provisioning and startup (optional reboot-survival scheduled task).
    • uninstall.ps1 / uninstall-keycloak.ps1 — clean teardown.
    • setup-vm-prereqs.ps1 — fresh-VM bootstrap.
    • yopass-docker.ps1 — optional one-time-credential-link stack.
    • README.md — full install guide (prerequisites, TLS/HTTPS, OIDC providers, upstream TLS verification, next steps, troubleshooting).
  • windows-install/docker/ — the Docker Compose stack for the PostgreSQL and optional Yopass paths: docker-compose.yml, docker-compose.yopass.yml, .env.example, init/01-create-adminapp-user.sh (least-privilege PostgreSQL role), and a README.md.
  • .gitignore — ignores the installer-generated docker/.env (holds database secrets), install-summary.txt, and Node build artifacts.

The installer-generated docker/.env is intentionally excluded; docker/.env.example documents the required variables.

Architectural Decisions

  • httpPlatform hosting (not iisnode): iisnode is unmaintained; the Microsoft HTTP Platform Handler (or the LeXtudio HTTP Bridge) proxies to a Node child on an IIS-assigned loopback port.
  • TLS always-on: standalone IIS sites on 4443 (FE) and 3443 (API); 4200/3333 redirect to HTTPS; a self-signed certificate is generated and auto-trusted to LocalMachine\Root when no certificate is supplied; enforcing CSP.
  • Least-privilege database access: the app connects as a dedicated non-sa / non-superuser login (edfi_adminapp on SQL Server as db_owner of sbaa; edfiadminapp on PostgreSQL owning public with CONNECT + CREATE only, never a DB-wide GRANT ALL).
  • Per-install data-encryption key: generated per install, recorded in the Administrators-only install summary, reused (not rotated) on idempotent re-runs.
  • Provider-agnostic OIDC (table-driven): Keycloak, Entra ID, and Google share one code path; the redirect URI is derived from the actual oidc row id (no hardcoded /callback/1). Keycloak is the local example provider.
  • Docker optional; PostgreSQL loopback-bound by default (127.0.0.1), with an opt-in for remote exposure.
  • Delivered as a dedicated repository (this move) rather than living inside the Admin App source tree.

Testing

Automated

None — these are deployment / orchestration scripts with no unit-testable surface. All scripts are AST-parse-clean. Validation is end-to-end and manual (below).

Manual — Full E2E matrix (against Admin App v4.0.1, on Windows 11 + IIS)

All 15 paths executed on a clean box; every path listed passed. The code in this PR already incorporates the fixes surfaced during E2E (see Known Limitations).

Path Scenario Result
P1 MSSQL + Keycloak, HttpBridge — happy path PASS
P2 MSSQL + Keycloak, HttpPlatformHandler (2nd handler) PASS
P6 TLS end to end (bindings, 301 redirect, self-signed auto-trust, enforcing CSP) PASS
P7 Idempotent re-run (key reused, oidc row not duplicated, Keycloak client reconciled) PASS
P8 Uninstall returns a clean box (FAIL count 0) PASS
P9 Security assertions (least-priv DB, security headers both sites, no plaintext secrets) PASS
P3 PostgreSQL + Docker + Keycloak, fresh volume — app boots, least-priv role, loopback bind PASS
P4 PostgreSQL + Docker, existing volume (re-run sync, no GRANT ALL) PASS
P5 Entra ID + MSSQL — LIVE browser login PASS
P13 Google Workspace + MSSQL — LIVE browser login PASS
P14 Entra ID + PostgreSQL/Docker — LIVE (closes EDFI-2774 both-engines) PASS
P15 Google Workspace + PostgreSQL/Docker — LIVE PASS

E2E highlights:

  • Node binds the IIS-assigned loopback port (not a fixed 3333); API → 401, FE → 200 with SPA fallback.
  • Security headers on both sites: HSTS, enforcing Content-Security-Policy, Referrer-Policy, X-Content-Type-Options: nosniff, X-Frame-Options: DENY; X-Powered-By absent.
  • OIDC redirect URI id-agnostic — the printed callback/<id> matches the actual oidc row id on both engines.
  • Entra ID OIDC seeding validated on both SQL Server (P5) and PostgreSQL (P14) — satisfies EDFI-2774.
  • Google accepted the https://localhost:3443 custom-port redirect at registration.

Known Limitations / Follow-Up

  • External-IdP sign-out is still Keycloak-specific: post-logout redirects to a Keycloak-style logout path, which returns 404 on Entra/Google. Generalized separately in EDFI-2772 / PR #211; lands in the next Admin App release. Not a blocker for this suite.
  • In-app Account Management link is still Keycloak-specific in the Admin App UI (Keycloak fallback, not hidden when the account URL is unset) for external IdPs. Generalized separately in EDFI-2786 / PR #214; lands in a future Admin App release. Note this affects only the link rendered inside the app — the install summary already prints a provider-appropriate account URL (e.g. myaccount.microsoft.com, myaccount.google.com). Not a blocker for this suite.
  • API config-template hardening (secure SSL_VERIFICATION default, remove an unused management secret) is tracked as EDFI-2813 against the Admin App repository; it lands in Admin App v4.1 and is not required for a v4.0.1 install (the installer injects config via NODE_CONFIG at deploy time).
  • This suite should be re-validated against Admin App v4.1 when it releases.

Checklist

  • Manually validated end to end (happy path + error paths) across both engines and all three IdPs
  • No commented-out code or TODO comments
  • Installer-generated secrets file (docker/.env) excluded from version control
  • PR focused on importing the windows-install suite only
  • Reviewer has read the diff

Import the windows-install script suite into this dedicated repository as a
sibling installation method alongside quick-start/. The scripts automate an
end-to-end Windows/IIS install of the Ed-Fi Admin App (v4.0.1 and above)
with either SQL Server or a Dockerized PostgreSQL backing store, and
Keycloak, Entra ID, or Google Workspace as the OIDC identity provider.

Includes the phased installer (install-all plus the 00-06 per-section
scripts), Keycloak setup/start, uninstall, the VM prerequisite bootstrap,
and the docker/ compose stack for the PostgreSQL and optional Yopass paths.
TLS is on by default, the API runs under the httpPlatform handler, and the
app connects with a least-privilege database login and a per-install
data-encryption key.

Validated end-to-end against Admin App v4.0.1 across SQL Server and
PostgreSQL with Keycloak, Entra ID, and Google before this import.
@analiliagutierrez
analiliagutierrez marked this pull request as ready for review July 14, 2026 17:29
@analiliagutierrez analiliagutierrez changed the title EDFI-2776 Add Windows IIS installation scripts for the Ed-Fi Admin App EDFI-2776 Add Windows IIS installation scripts Jul 14, 2026
Document how to work on the windows-install method: prerequisites, the
script layout, install commands per database engine and identity provider,
the key install-all parameters, coding conventions, the security invariants
to preserve, environment notes, the end-to-end testing expectation, and the
pull-request workflow.
After moving the install scripts into this dedicated repo, -SourcePath no
longer defaulted to an Admin App checkout. install-all.ps1 now resolves the
source: it honors an existing co-located or sibling checkout and otherwise
clones Ed-Fi-AdminApp at the newest stable release (-AdminAppRef 'latest',
resolved via the GitHub releases API; override to pin a tag). The standalone
00/03/04 scripts resolve the same sibling path; the README, -SourcePath help,
and uninstall notes are aligned with the separate-repo layout.
The remove-then-add that keeps NPM_CONFIG_CACHE and NODE_CONFIG idempotent
warned on a fresh install, where there is nothing to remove yet; -ErrorAction
does not suppress that warning. Add -WarningAction SilentlyContinue so the
first-run output stays clean. No behavior change.

@adiaz-msdf adiaz-msdf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review - requesting changes

First off: this is a really strong suite - the error-handling discipline, hash-verified downloads, SecureString handling, and docs are well above typical installer scripts, and the E2E matrix shows. That said, I found six issues I'd consider blocking. Four of them are one shared defect class (secret/user values interpolated into SQL/URL/form strings without escaping), so the fixes are all targeted.

# Severity Location Issue
1 High 05-deploy-api.ps1:423, 06-deploy-fe.ps1:241 HSTS on localhost breaks the default Keycloak login
2 High 02-prereqs-sql.ps1:213,254, 05-deploy-api.ps1:729 Secrets exposed on sqlcmd process command lines
3 High install-all.ps1:584 Unescaped password in superuser SQL (psql)
4 High docker/init/01-create-adminapp-user.sh:19 Same unescaped interpolation in the container init SQL
5 High idp-keycloak-setup.ps1:412,676 Keycloak credentials not URL-encoded in token requests
6 High README.md:48,123,143,235 Documented commands fail [SecureString] parameter binding

1. HSTS pin on localhost breaks the default Keycloak flow

05-deploy-api.ps1:423 / 06-deploy-fe.ps1:241

Both sites emit Strict-Transport-Security: max-age=31536000; includeSubDomains, and since the installer auto-trusts its self-signed cert, the browser records a valid one-year HSTS pin for the host localhost. HSTS is port-agnostic, so after the first visit to https://localhost:4443 the browser rewrites the default issuer http://localhost:8080 to https://localhost:8080 - which Keycloak (dev mode) doesn't serve. Login fails with connection refused, and the pin affects every other localhost HTTP service on the machine for a year.

Suggestion: emit HSTS only when a real hostname / CA-issued cert is supplied (skip it on the localhost self-signed path), or serve Keycloak over HTTPS.

2. Secrets on process command lines via sqlcmd -Q

02-prereqs-sql.ps1:213 (sa password), :254 (app-login password), 05-deploy-api.ps1:729 (OIDC client secret)

$saQuery = "ALTER LOGIN sa WITH PASSWORD = '$escapedPw'; ALTER LOGIN sa ENABLE;"
# later:  sqlcmd ... -Q $saQuery

The T-SQL containing the plaintext secret becomes a sqlcmd argument - readable by any local user via process listings while it r-line auditing (event 4688 / Sysmon). It also contradicts the suite's own design: 02 uses SQLCMDPASSWORD and promises "never on a command line" (line 82), and the psql branch of the OIDC block already pipes SQL via stdin correctly.

Suggestion: write the statement to an Administrators-only temp file and pass -i (delete in finally), or pipe via stdin lik

3. Unescaped password in superuser SQL

install-all.ps1:584

ALTER USER "$PostgresAppUser" WITH PASSWORD '$PostgresAppPasswordPlain';

Runs as the postgres superuser with no quote-escaping. The script's own complexity check encourages symbols, so a password like Summ'er2026! produces a psql syntax error with a misleading "check -PostgresSuperuserPassword" hint - and a crafted value is SQL injection as superuser. Note $OidcClientId is escaped (-replace "'", "''") at ~890, so this is just an omission.

Suggestion: apply the same '' escaping to the password and double any " in the identifiers, or use psql -v variables.

4. Same injection in the Docker first-boot init script

docker/init/01-create-adminapp-user.sh:19

CREATE USER "${ADMIN_APP_DB_USER}" WITH PASSWORD '${ADMIN_APP_DB_PASSWORD}';

Unquoted heredoc, so bash expands the .env password straight into SQL. With ON_ERROR_STOP=1, a password containing ' aborts the entrypoint on first boot and the volume never initializes - a bricked container that's hard to diagnose.

Suggestion: psql variables quote safely:

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
     -v user="$ADMIN_APP_DB_USER" -v pw="$ADMIN_APP_DB_PASSWORD" <<-'EOSQL'
  CREATE USER :"user" WITH PASSWORD :'pw';
  GRANT CONNECT, CREATE ON DATABASE :"db" TO :"user";
EOSQL

(quoted <<-'EOSQL' so bash stops expanding; pass POSTGRES_DB as -v db= too).

5. Keycloak credentials not URL-encoded in token requests

idp-keycloak-setup.ps1:412 (admin token) and the probe at ~676

-Body "grant_type=password&client_id=admin-cli&username=$AdminUser&password=$AdminPasswordPlain"

Any &, =, +, %, or # in the password corrupts the form body invalid_grant. Worse, the recovery guidance then steers keycloak\data`, destroying a working realm over an encoding bug.

Suggestion: pass a hashtable as -Body (Invoke-RestMethod form-encodes it), or wrap each value in [Uri]::EscapeDataString(). Same for client_secret / password in the probe.

6. README quick-start commands don't run as written

README.md:48, :123, :143, ~:235

-SaPassword, -KeycloakAdminPassword, -OidcClientSecret, -TestUserPassword are [SecureString], so passing 'your-sa-password' fails parameter binding immediately - the canonical documented command cannot be executed. It also contradicts CONTRIBUTING.md ("never pass a plaintext literal") and the script's own .EXAMPLE blocks, which do it right.

Suggestion: switch the examples to the script's own style:

.\install-all.ps1 -IdpProvider keycloak `
  -SaPassword (Read-Host -AsSecureString 'sa password') `
  -KeycloakAdminPassword (Read-Host -AsSecureString 'Keycloak admin password') `
  -OidcClientSecret (Read-Host -AsSecureString 'OIDC client secret') `
  -TestUserPassword (Read-Host -AsSecureString 'test user password')

While in there: the README never mentions -AppDbPassword (required in the default mssql mode per the script's own help) and has ppPassword/-PostgresSuperuserPassword`) - worth adding to fully cover EDFI-2776's "usage README and required variables"
criterion.


Disclosure: this review was substantially AI-assisted. Please treat the findings as input for human review rather than a final verdict

Keycloak 26.6 supports OpenJDK 17, 21, and 25 (Java 25 is LTS). Update the
two "Java 17 or 21" comments in idp-keycloak-setup.ps1 to "17, 21, or 25" so
they match the pinned Keycloak 26.6.1 and the installation guide.

@adiaz-msdf adiaz-msdf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Resolve the six findings from the PR #2 review:

- Emit HSTS only with a real hostname / CA cert; omit it on the
  self-signed localhost path so the one-year, port-agnostic pin no
  longer rewrites Keycloak dev (:8080) to https and breaks login.
- Run secret-bearing sqlcmd statements from an Administrators-only
  temp file via -i instead of -Q, keeping the secret off the process
  command line (02-prereqs-sql.ps1, 05-deploy-api.ps1 OIDC upsert).
- Escape the app password and identifiers in the psql superuser sync
  (install-all.ps1) to prevent syntax errors and SQL injection.
- Quote the container init heredoc and use psql variables so a
  special character no longer bricks PostgreSQL first boot.
- Send Keycloak token requests as hashtable bodies so credentials
  are URL-encoded.
- Fix README quick-start commands to use SecureString parameters and
  document -AppDbPassword and the PostgreSQL passwords.

Also add .gitattributes (*.sh text eol=lf) so the container init
script stays LF and cannot be checked out as CRLF under autocrlf.
@analiliagutierrez

Copy link
Copy Markdown
Contributor Author

Review - requesting changes

First off: this is a really strong suite - the error-handling discipline, hash-verified downloads, SecureString handling, and docs are well above typical installer scripts, and the E2E matrix shows. That said, I found six issues I'd consider blocking. Four of them are one shared defect class (secret/user values interpolated into SQL/URL/form strings without escaping), so the fixes are all targeted.

Severity Location Issue

1 High 05-deploy-api.ps1:423, 06-deploy-fe.ps1:241 HSTS on localhost breaks the default Keycloak login
2 High 02-prereqs-sql.ps1:213,254, 05-deploy-api.ps1:729 Secrets exposed on sqlcmd process command lines
3 High install-all.ps1:584 Unescaped password in superuser SQL (psql)
4 High docker/init/01-create-adminapp-user.sh:19 Same unescaped interpolation in the container init SQL
5 High idp-keycloak-setup.ps1:412,676 Keycloak credentials not URL-encoded in token requests
6 High README.md:48,123,143,235 Documented commands fail [SecureString] parameter binding

1. HSTS pin on localhost breaks the default Keycloak flow

05-deploy-api.ps1:423 / 06-deploy-fe.ps1:241

Both sites emit Strict-Transport-Security: max-age=31536000; includeSubDomains, and since the installer auto-trusts its self-signed cert, the browser records a valid one-year HSTS pin for the host localhost. HSTS is port-agnostic, so after the first visit to https://localhost:4443 the browser rewrites the default issuer http://localhost:8080 to https://localhost:8080 - which Keycloak (dev mode) doesn't serve. Login fails with connection refused, and the pin affects every other localhost HTTP service on the machine for a year.

Suggestion: emit HSTS only when a real hostname / CA-issued cert is supplied (skip it on the localhost self-signed path), or serve Keycloak over HTTPS.

2. Secrets on process command lines via sqlcmd -Q

02-prereqs-sql.ps1:213 (sa password), :254 (app-login password), 05-deploy-api.ps1:729 (OIDC client secret)

$saQuery = "ALTER LOGIN sa WITH PASSWORD = '$escapedPw'; ALTER LOGIN sa ENABLE;"
# later:  sqlcmd ... -Q $saQuery

The T-SQL containing the plaintext secret becomes a sqlcmd argument - readable by any local user via process listings while it r-line auditing (event 4688 / Sysmon). It also contradicts the suite's own design: 02 uses SQLCMDPASSWORD and promises "never on a command line" (line 82), and the psql branch of the OIDC block already pipes SQL via stdin correctly.

Suggestion: write the statement to an Administrators-only temp file and pass -i (delete in finally), or pipe via stdin lik

3. Unescaped password in superuser SQL

install-all.ps1:584

ALTER USER "$PostgresAppUser" WITH PASSWORD '$PostgresAppPasswordPlain';

Runs as the postgres superuser with no quote-escaping. The script's own complexity check encourages symbols, so a password like Summ'er2026! produces a psql syntax error with a misleading "check -PostgresSuperuserPassword" hint - and a crafted value is SQL injection as superuser. Note $OidcClientId is escaped (-replace "'", "''") at ~890, so this is just an omission.

Suggestion: apply the same '' escaping to the password and double any " in the identifiers, or use psql -v variables.

4. Same injection in the Docker first-boot init script

docker/init/01-create-adminapp-user.sh:19

CREATE USER "${ADMIN_APP_DB_USER}" WITH PASSWORD '${ADMIN_APP_DB_PASSWORD}';

Unquoted heredoc, so bash expands the .env password straight into SQL. With ON_ERROR_STOP=1, a password containing ' aborts the entrypoint on first boot and the volume never initializes - a bricked container that's hard to diagnose.

Suggestion: psql variables quote safely:

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
     -v user="$ADMIN_APP_DB_USER" -v pw="$ADMIN_APP_DB_PASSWORD" <<-'EOSQL'
  CREATE USER :"user" WITH PASSWORD :'pw';
  GRANT CONNECT, CREATE ON DATABASE :"db" TO :"user";
EOSQL

(quoted <<-'EOSQL' so bash stops expanding; pass POSTGRES_DB as -v db= too).

5. Keycloak credentials not URL-encoded in token requests

idp-keycloak-setup.ps1:412 (admin token) and the probe at ~676

-Body "grant_type=password&client_id=admin-cli&username=$AdminUser&password=$AdminPasswordPlain"

Any &, =, +, %, or # in the password corrupts the form body invalid_grant. Worse, the recovery guidance then steers keycloak\data`, destroying a working realm over an encoding bug.

Suggestion: pass a hashtable as -Body (Invoke-RestMethod form-encodes it), or wrap each value in [Uri]::EscapeDataString(). Same for client_secret / password in the probe.

6. README quick-start commands don't run as written

README.md:48, :123, :143, ~:235

-SaPassword, -KeycloakAdminPassword, -OidcClientSecret, -TestUserPassword are [SecureString], so passing 'your-sa-password' fails parameter binding immediately - the canonical documented command cannot be executed. It also contradicts CONTRIBUTING.md ("never pass a plaintext literal") and the script's own .EXAMPLE blocks, which do it right.

Suggestion: switch the examples to the script's own style:

.\install-all.ps1 -IdpProvider keycloak `
  -SaPassword (Read-Host -AsSecureString 'sa password') `
  -KeycloakAdminPassword (Read-Host -AsSecureString 'Keycloak admin password') `
  -OidcClientSecret (Read-Host -AsSecureString 'OIDC client secret') `
  -TestUserPassword (Read-Host -AsSecureString 'test user password')

While in there: the README never mentions -AppDbPassword (required in the default mssql mode per the script's own help) and has ppPassword/-PostgresSuperuserPassword`) - worth adding to fully cover EDFI-2776's "usage README and required variables" criterion.

Disclosure: this review was substantially AI-assisted. Please treat the findings as input for human review rather than a final verdict

Thank you! The comments have been addressed.

@stevenarnold-ed-fi

Copy link
Copy Markdown
Contributor
image

I have some concerns about what the reset sa is doing, is that really resetting the sa password? I don't think that will work on an existing system, let's talk about it.

Comment thread windows-install/setup-vm-prereqs.ps1 Outdated
Comment thread windows-install/setup-vm-prereqs.ps1 Outdated
Comment thread windows-install/CONTRIBUTING.md Outdated
The Admin App builds its DB connection string as a URL and interpolates the
credentials without URL-encoding them, so a password containing a character
that is structural in a URL (or needs percent-encoding) is corrupted at
connect time and the API aborts startup with an opaque "Login failed for
user". Add a Test-DbPasswordUrlSafe guard that rejects such passwords up
front in 02-prereqs-sql.ps1, 05-deploy-api.ps1, and install-all.ps1, with a
clear message. Temporary workaround until the Admin App URL-encodes its
credentials; password strength is unaffected (CHECK_POLICY still needs any 3
of 4 character categories).
The SQL Server bootstrap no longer enables, resets, or connects as sa.
The database and the least-privilege edfi_adminapp login are now
provisioned under Windows Authentication, so the installer must run as a
Windows account that is a SQL Server sysadmin. The app continues to
connect as the dedicated non-sysadmin edfi_adminapp login.

- 02-prereqs-sql.ps1: drop -SaPassword and the sa enable/ALTER/verify
  steps; create the database via Windows Auth.
- install-all.ps1: drop -SaPassword; run the post-deploy user/oidc
  queries as edfi_adminapp (matching the pgsql path).
- uninstall.ps1: drop the database and login via Windows Auth only.
- 00-check-prereqs.ps1: remove the sa-reset risk checks.
- README.md / CONTRIBUTING.md: document the Windows-sysadmin precondition.
The earlier wording pass skipped fenced code blocks and tables; spell out
the leftover shorthand there (FE, VM, DB, PG, certs, Windows Auth,
least-priv) in README.md and CONTRIBUTING.md.
Windows Server 2019/2022 do not ship winget, which the scripts use to
install Node.js, OpenJDK, SQL Server, and Git. Document it as a
prerequisite in the README (install it first on Server, at your own
risk), have 00-check-prereqs.ps1 flag when it is missing, and fail early
with clear guidance at each point of use (setup-vm-prereqs.ps1,
03-prereqs-node.ps1, idp-keycloak-setup.ps1) instead of a cryptic
"'winget' is not recognized" mid-install. Also suppress the
Invoke-WebRequest progress bar in 01-prereqs-iis.ps1 so the MSI downloads
run at full speed on PowerShell 5.1.
@analiliagutierrez

Copy link
Copy Markdown
Contributor Author
image I have some concerns about what the reset sa is doing, is that really resetting the sa password? I don't think that will work on an existing system, let's talk about it.

Good catch, thanks. With the dedicated edfi_adminapp, sa isn't needed for anything anymore; I removed it from the scripts flow entirely. The database and the edfi_adminapp login are now provisioned under Windows Authentication; sa is never enabled, reset or used.

The URL-safe guard now also validates the database username (-AppDbUsername /
-PgDbUsername / -PostgresAppUser), not only the password: the same characters
break the username in the app's URL-form connection string. Reuses
Test-DbPasswordUrlSafe and neutralizes its message to cover both credentials.
@analiliagutierrez
analiliagutierrez merged commit 36e31a1 into main Jul 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants