Spara inte känsliga applikationsdata i ett offentligt källkodsrepo

Inledning

Det finns tonvis med blogposter som handlar om att man inte ska låta känsliga konfigurationsdata hamna i ett källkodsrepo. Det är i högsta grad en god idé att låta bli, betänk följande utdrag ur en godtycklig web.config, exempel:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="DefaultConnection"
         connectionString="MY SECRET CONNECTION STRING"
         providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="BankAccountNumber" value="MY SECRET VALUE" />
  </appSettings>
</configuration>
Original ur C:\Users\haunstm\Desktop\hemsamariten\homecontrol\Web.config

Kanske inte så bra om den hamnar i ett offentligt källkodsrepo (t ex gratisversionen av GitHub)? Det tycker åtminstone inte jag. Det finns tack och lov mängder av sätt att komma runt det hela lite beroende på hur man har konfigurerat miljön kring sin känsliga databas. (Vi antar för nedanstående exempel att det är en sådan som vi vill skydda med en ickepublik/offentlig connectionString).

SQL Server

På min produktionsserver kör jag Microsoft SQL Server 2014. När jag konfigurerade databasmotorn för första gången ombads jag att ange huruvida jag ville ha Windows Authentication mode eller SQL Server and Windows Authentication mode. Oavsett vad jag valde var det ingenting som jag inte kan/kunde ändra på vid senare tillfälle. Kort sagt, med Windows Authentication mode måste databasanvändaren vara godkänd av domänkontrollanten och godkänd användare i databasen. Med SQL Server and Windows Authentication mode kan man vara en godtycklig användare som tilldelats rättigheter och lösenord efter behov (men det ska inte den här bloggposten handla om. Vi nöjer oss med att konstatera att SQL Server erbjuder oss möjligheterna).

Men hur gör man då för att känsliga data inte skall offentliggöras?

Både <connectionStrings/> och <appSettings/> har parametrar som möjliggör att data kan läsas in under runtime från externa filer. Vid runtime integreras innehållet med de ursprungliga Web.config (eller app.config beroende på vad man utgår från) och resultatet blir transparent för konfigurationsfilskonsumenten.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings
    configSource="ConnectionStrings.config"/>
  <appSettings>
    <add key="BankAccountNumber"
         value="MY SECRET VALUE" />
  </appSettings>
</configuration>
Modifierad C:\Users\haunstm\Desktop\hemsamariten\homecontrol\Web.config
 
<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
  <add name="DefaultConnection"
       connectionString="MY SECRET CONNECTION STRING"
       providerName="System.Data.SqlClient" />
</connectionStrings>
 C:\inetpub\sensitiveData\hemsamariten\ConnectionStrings.config

På vilket sätt hjälper detta mig när jag vill skydda mina data?

När vi checkar in/pushar kod till vårt källkodsrepo ignorerar vi alltid ConnectionStrings.config. Eftersom filen inte ligger i versionshanterad Visual Studio – solution, och dessutom i en avlägsen mapp, är risken inte särskilt stor att vi av misstag gör en felincheckning. För att praktiskt hantera dessa hemliga data i filen har jag manuellt deployat den till produktionsservern (och i förekommande fall även till andra utvecklare som haft behov.)

Finns några Gotchas?

-Absolut, minst ett par stycken, här är ett par!

  • Ett aber är att configSource-parametern måste sättas så att den refererar till en fil i samma mapp, eller till en undermapp, i förhållande till Web.config!

  • Ett annat att intellisense kommer att klaga på att den inte hittar filen ConnectionStrings.config. Det är helt korrekt eftersom filen inte finns där för tillfället.

    I det nedanstående kommer vi att titta på hur vi med hjälp av ett pre build event kan kopiera in ConnectionStrings.config så att filen hamnar i samma mapp som C:\Users\haunstm\Desktop\hemsamariten\homecontrol\Web.config.

Säkerställ att ConnectionStrings.config att filen hamnar i samma mapp som C:\Users\haunstm\Desktop\hemsamariten\homecontrol\Web.config.

Genom att konfigurera Visual Studio så att en filkopiering sker innan huvudbygget kommer vi att få vår externa konfigurationsfil där vi vill ha den. Om vi gör detta medelst ett s k pre build event som vi lagrar i projektfilen, kommer sannolikt eventuella CI-system (som kontinuerligt checkar ut kod från vårt repo, bygger projektet och slutligen deployar det på vår produktionsserver) att hantera kopieringen på samma sätt.

Förslag på praktiska moment

I filsysstemet

  1. Skapa en mapp för känsliga data. Förslagsvis C:\inetpub\sensitiveData\hemsamariten.
    • På en utvecklarmaskin.
    • På en annan utvecklarmaskin om behov finns.
    • På en produktionsserver.

    För att inte behöva göra ytterligare konfigurationer förutsätts mappen C:\inetpub\sensitiveData\hemsamariten på samtliga maskiner!

  2. Kopiera manuellt filen med det känsliga datat till respektive dators mapp enligt ovan.

I Visual Studio

  1. Skapa ett "pre build event" i Visual Studio som sköter kopieringen.
    Solution Explorer > Högerklicka på projektet > Properties > Build Events
  2. Välj ”Edit Pre-build ...” och kopiera in följande MS-DOS-script:
    @echo off
    echo Copying sensitive connectionstring file to target directory ...
    XCOPY "C:\inetpub\sensitiveData\hemsamariten\ConnectionStrings.config" "$(ProjectDir)" /s /i /y

    if errorlevel 5 (
      echo ERROR - Disk write error occurred.
      GOTO XCOPYFAIL
    )

    if errorlevel 4 (
      echo ERROR - Initialization error occurred. There is not enough memory or disk space, or you entered an invalid drive name or invalid syntax on the command line.
      GOTO XCOPYFAIL
    )

    if errorlevel 2 (
      echo ERROR - The user pressed CTRL+C to terminate xcopy.
    )

    if errorlevel 1 (
      echo ERROR - No files were found to copy.
      GOTO XCOPYFAIL
    )

    echo SUCCESS - Files were copied without error.
    exit /b [0]

    :XCOPYFAIL

    MS-DOS-script för filkopiering

  3. Klicka på Ok och kör projektet!

Om allt gått väl, och kopieringen har lyckats, kan vi köra igång projektet. Vår ursprungliga C:\Users\haunstm\Desktop\hemsamariten\homecontrol\Web.config har till produktionsversionen integrerats med våra känsliga data (i \bin-mappen).

Annonser