/

/

Fra krise til ninja - Hvordan sikre hemmeligheter i koden

/

/

Fra krise til ninja - Hvordan sikre hemmeligheter i koden

/

/

Fra krise til ninja - Hvordan sikre hemmeligheter i koden

/

/

Fra krise til ninja - Hvordan sikre hemmeligheter i koden

Vårt delingshjørne

Fra krise til ninja - Hvordan sikre hemmeligheter i koden

Fra krise til ninja - Hvordan sikre hemmeligheter i koden

Fra krise til ninja - Hvordan sikre hemmeligheter i koden

Lars Espen

Nordhus

Chief Technology Officer (CTO) & Senior Systemutvikler

Chief Technology Officer (CTO) & Senior Systemutvikler

18. desember 2024

Utvikling

Problemet med hvor man skal plassere connection strings, client secrets og lignende er et evig problem. Uansett hvordan man vrir og vender på det må det som regel lagres noe gull noe sted. Over tid har både min forståelse og verktøyene tilgjengelig for secrets i C#+Azure blitt mye bedre, noe som igjen har ført til en god del forbedringer. Den optimale løsningen dersom man har kontroll på alle komponenter og de alle kjører i Azure sammen, er managed identity. Dessverre er ikke infrastrukturen alltid slik. Av og til har man integrasjoner til tredjepart, noe kjører on-prem eller hemmelighetene skal brukes til noe annet enn direkte tilgang.

I denne bloggen skal jeg ta dere gjennom hvorfor noen løsninger er bedre enn andre og hvordan å sette dem opp. Ut ifra ditt oppsett kan det hende man stopper et sted på veien og sier seg fornøyd, eller finner en annen måte å komme seg rundt de oppgitte svakhetene. Her er det jeg har lært så langt (fra nivå1-dårlig til nivå8-ninja) 


Nivå 1 → Passord rett i koden

Det er fort gjort å bare skulle fikse noe fort og glemmer å fjerne slike implementasjoner eller at man er ny i programmeringsverden, men denne typen kode er litt krise å finne i produksjon …

✅ God ytelse
❌ Unngå bygg ved endring av connection string
❌ Ingen passord på utviklermaskiner
❌ Ingen passord i GIT-repo
❌ Ingen passord åpent på server
❌ Unngå deploy ved endring av connection string
❌ Lett koordinering av oppdateringer på tvers av applikasjoner


var token = "sadsajhdhgiehuhikdhajkhskhbkhbrfsvcbjhrsbjhcd";
using var myClient = InfluxDBClientFactory.Create("http://localhost:8086", token);
using var write = myClient.GetWriteApi();
action(write);


Nivå 2 → Passord i app-settings-fil

Ved å legge connection string og annet i app-settings.json fila kan vi i hvert fall endre verdi uten å bygge hele prosjektet på ny. Man kan i tillegg lage en app-settings fil pr miljø og på den måten ha konfigurasjon og passord satt opp pr miljø. Dette er dessverre fortsatt en del av kildekoden og har fortsatt en del problemer: 

✅ God ytelse
✅ Unngå bygg ved endring av connection string
❌ Ingen passord på utviklermaskiner
❌ Ingen passord i GIT-repo
❌ Ingen passord åpent på server
❌ Unngå deploy ved endring av connection string
❌ Lett koordinering av oppdateringer på tvers av applikasjoner


{
  "Dhis2": {
    "ApiToken": "ApiToken d2p_sdsadsadsade3desdyg1yg2ugyggsadqswe3dsadc",
    "BaseUrl": "https://test-dhis2.stuff.com/"
  }
}


Nivå 3 → value-substitution i byggpipeline + user sercrets

Passord i app-settings-fil kan erstattes i byggsteget med secrets. Dette gjøres som en task i build pipleline med value-substitution og user secrets lokalt. Dette gir mulighet for secrets pr miljø og sikkerhet på at hemmeligheter ikke kommer seg til Github.  

✅ God ytelse
✅ Unngå bygg ved endring av connection string
✅ Ingen passord på utviklermaskiner
✅ Ingen passord i GIT-repo
✅ Ingen passord åpent på server
❌ Unngå deploy ved endring av connection string
❌ Lett koordinering av oppdateringer på tvers av applikasjoner

# File transform v2
# Replace tokens with variable values in XML or JSON configuration files.
- task: FileTransform@2
  inputs:
    folderPath: '$(System.DefaultWorkingDirectory)/**/*.zip' # string. Required. Package or folder. Default: $(System.DefaultWorkingDirectory)/**/*.zip.
    #enableXmlTransform: true # boolean. XML transformation. Default: true.
    #xmlTransformationRules: '-transform **\*.Release.config -xml **\*.config' # string. Optional. Use when enableXmlTransform == true. XML Transformation rules. Default: -transform **\*.Release.config -xml **\*.config.
  # Variable Substitution
    #jsonTargetFiles: # string. JSON target files. 
    #xmlTargetFiles: # string. XML target files

 

Nivå 4 → Passord i env

Man kan for eksempel sette app-settings-env i Azure web apps eller lignende. På den måten har man secrets helt uavhengig av bygg og deploy av koden og pr miljø. Dette er en ganske ok løsning for prosjekter der man har god kontroll på tilganger og infrastruktur som kode satt opp. Dette er spesielt vanlig ved kubernetes oppsett og gir sikkerhet på at secrets ikke kommer seg til Github. Men problemet er som regel å finne en god måte å sette passordene for infrastruktur koden. Det fører også ofte til at man må kjøre infrastruktur pipeline for hver deploy av ny kode for å være sikker på at nye secrets blir med. 

✅ God ytelse
✅ Unngå bygg ved endring av connection string
✅ Ingen passord på utviklermaskiner
✅ Ingen passord i GIT-repo
❌ Ingen passord åpent på server
✅ Unngå deploy ved endring av connection string
❌ Lett koordinering av oppdateringer på tvers av applikasjoner

 

 

Nivå 5 → Keyvault-oppslag i koden  

Lesing av secrets ved behov fra keyvault ved hjelp av denne typen kode:

string keyVault_URL = configuration.GetValue<string>("KeyVault_URL");
var maskinporten_secret = client.GetSecret("Maskinporten--Secret").Value.Value

Dette fører til at man potensielt slår opp secrets mange ganger og problemer med utvikling lokalt. DefaultAzureCredentials gir deg mulighet til å bruke aktiv visual strudio bruker og managed idenity til å lese ut secrets uten å måtte ha client secret noe sted. En annen positiv ting med det å få secrets inn i keyvault er at flere språk kan lese herifra og man støtter både managed identity, roller og har audit logg innebygget. 

❌ God ytelse
✅ Unngå bygg ved endring av connection string
✅ Ingen passord på utviklermaskiner
✅ Ingen passord i GIT-repo
✅ Ingen passord åpent på server
✅ Unngå deploy ved endring av connection string
❌ Lett koordinering av oppdateringer på tvers av applikasjoner

 

Nivå 6 → App-settings-env-kevault

Det er mulig å la azure lese secrets med managed identity dynamisk ved å gi appsetting verdien:

På denne måten kan man la Azure gjøre jobben med oppslag av secret og migrere dette med app settings hver gang man restarter serveren. Dette alternativet er en utvidelse av nivå 4.

✅ God ytelse
✅ Unngå bygg ved endring av connection string
✅ Ingen passord på utviklermaskiner
✅ Ingen passord i GIT-repo
✅ Ingen passord åpent på server
✅ Unngå deploy ved endring av connection string
❌ Lett koordinering av oppdateringer på tvers av applikasjoner

 

Nivå 7 → Secret ninja!

Konfigurere automatisk innlesing av secrets inn i IConfiguration som del av setup med koden under. 


Program.cs

builder.Configuration.AddAzureKeyVault(
    new Uri(builder.Configuration["KeyVault_URL"]),
    new DefaultAzureCredential(),
    new DottableKeyVaultSecretManager());


Hjelpeklasse

public class DottableKeyVaultSecretManager : KeyVaultSecretManager
{
    public override string GetKey(KeyVaultSecret secret)
    {
        var result = secret.Name.Replace("--", ConfigurationPath.KeyDelimiter);

        return result;
    }
}


Dependencies

Azure.Extensions.AspNetCore.Configuration.Secrets
Azure.Identity

Dette gjør at man kan ha secrets i keyvault og oppdatere dem der løpende enten manuelt eller med IAC. Samtidig kan resten av prosjektet ditt bruke IConfiguration som vanlig og hente ut sammenstilling av appsettings.json, appsettings.dev.json, user secrets, key vault secrets og manuell environment override. Det å ha muligheten til å legge secrets og config i alle disse 5 config stedene på et kjørende prosjekt kan være litt forvirrende, men gir også en utrolig fleksibilitet. Ved å ha mulighet til å sette opp gode kjøreregler på hvordan man skal jobbe med disse i teamet, synes jeg dette er en utrolig bra løsning.

✅ God ytelse
✅ Unngå bygg ved endring av connection string
✅ Ingen passord på utviklermaskiner
✅ Ingen passord i GIT-repo
✅ Ingen passord åpent på server
✅ Unngå deploy ved endring av connection string
❌ Lett koordinering av oppdateringer på tvers av applikasjoner

 

Nivå 8 → Config & Secret ninja!

Det siste steget bruker Azure App Configuration sammen med keyvault for å også kunne konfigurere dette på tvers av app og slippe spessialkoden over. Konseptet her er at man får en sentral server med alle konfigurasjoner på tvers av applikasjon. Dette gjør at man kan se oversikt over alle secrets og konfigurasjoner uten å nødvendigvis har rettigheter til å se selve hemmeligheten siden du ikke har tilgang i keyvault-et disse ligger i. Det gir også muligheten til å håndtere «feature toggles» på tvers av applikasjon som er veldig kraftig. 

✅ God ytelse
✅ Unngå bygg ved endring av connection string
✅ Ingen passord på utviklermaskiner
✅ Ingen passord i GIT-repo
✅ Ingen passord åpent på server
✅ Unngå deploy ved endring av connection string
✅ Lett koordinering av oppdateringer på tvers av applikasjoner

 

Oppsumering

Det er nok ikke alle som kommer til å være 100% enige med meg når det kommer til vektlegging av krav. Brukerbehovet og valg som hvor leverandør-uavhengig man har lyst å være, kan jo for eksempel avgjøre alt for noen. Dersom man kommer fra retningen plattformdrift eller bruker mange andre språk enn C#, skjønner jeg at alternativene som går rundt miljøvariable er en urokkelig sannhet, men da føler jeg man begrenser seg i en suboptimal løsning. Verktøyene som har blitt laget gjør at man kan få utrolig fleksible og gode løsninger som gjør at løsningen både er lett å drifte, videreutvikle og sikre. Det å kunne laste ned et prosjekt fra Git i din bedrift og bare kunne trykke play uten å måtte gjøre mer for å spinne opp en løsning som går mot et valgt miljø som dev eller test syntes jeg er magisk! 

Kanskje du liker:

Kanskje du liker:

Kanskje du liker:

Utvikling

18. desember 2024

Her er det jeg har lært så langt (fra nivå1-dårlig til nivå8-ninja) 

Utvikling

18. desember 2024

Her er det jeg har lært så langt (fra nivå1-dårlig til nivå8-ninja) 

Utvikling

21. april 2024

.net 8 med nye Identity Endpoints oppsett. Vi har tatt en en nærmere titt på det. Er Identity API Endpoints i .net 8 kroken på døra for tredjepartsautentisering?

Utvikling

21. april 2024

.net 8 med nye Identity Endpoints oppsett. Vi har tatt en en nærmere titt på det. Er Identity API Endpoints i .net 8 kroken på døra for tredjepartsautentisering?

Utvikling

1. mars 2024

Mange tenker på Techlead kun som en flink utvikler, mens Techleadene selv ofte tenker på seg selv som et teknisk orakel som bør bestemme det meste. Begge disse ytterpunktene står i veien for god verdiskaping. 

Utvikling

1. mars 2024

Mange tenker på Techlead kun som en flink utvikler, mens Techleadene selv ofte tenker på seg selv som et teknisk orakel som bør bestemme det meste. Begge disse ytterpunktene står i veien for god verdiskaping. 

Utvikling

18. desember 2024

Her er det jeg har lært så langt (fra nivå1-dårlig til nivå8-ninja) 

Utvikling

21. april 2024

.net 8 med nye Identity Endpoints oppsett. Vi har tatt en en nærmere titt på det. Er Identity API Endpoints i .net 8 kroken på døra for tredjepartsautentisering?

Utvikling

18. desember 2024

Her er det jeg har lært så langt (fra nivå1-dårlig til nivå8-ninja) 

Utvikling

21. april 2024

.net 8 med nye Identity Endpoints oppsett. Vi har tatt en en nærmere titt på det. Er Identity API Endpoints i .net 8 kroken på døra for tredjepartsautentisering?

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2024. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2024. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2024. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2024. All rights reserved.