RickardPettersson / swish-api-csharp

Swish For Merchant API Client .Net Standard Library
MIT License
29 stars 14 forks source link

Cert from KeyVault possible? #23

Closed toastmastern closed 2 years ago

toastmastern commented 2 years ago

Tried stream but with cloud its would perhaps be possible to simply add a "get from keyvault" instead to make it simpler and not require cert store on user account.

Snippet below might be of help? (this does not require a store to be opened) (if not perhaps have some kind of "skip open store and use X509KeyStorageFlags.MachineKeySet" as some kind of constructor params?)

public record CertificateSettings { public Uri? KeyVaultUri { get; init; } public string? Name { get; init; } }

private static X509Certificate2? GetCertificateFromKeyVault(CertificateSettings? certificate) { var secretClient = new SecretClient( certificate.KeyVaultUri, new DefaultAzureCredential() );

    var kvSecret = secretClient.GetSecret(certificate.Name);
    var kvCert = Convert.FromBase64String(kvSecret.Value.Value);
    var x509Cert = new X509Certificate2(kvCert, default(string?), X509KeyStorageFlags.MachineKeySet);

    return x509Cert;

}

// in DI use this as httphandler

    services.AddHttpClient<SwishRepository>((sp, httpClient) =>
    {
        var configuration = sp.GetRequiredService<IOptions<SwishSettings>>().Value;

        httpClient.BaseAddress = new Uri(configuration.BaseUrl!);
    }).ConfigurePrimaryHttpMessageHandler((sp) =>
    {
        var configuration = sp.GetRequiredService<IOptions<SwishSettings>>().Value;

        var handler = new HttpClientHandler();
        handler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => true;
        handler.ClientCertificateOptions = ClientCertificateOption.Manual;
        handler.ClientCertificates.Add(
        // this snippet only add keyvault certificate
        GetCertificateFromKeyVault(configuration.Certificate));

        return handler;
    });
RickardPettersson commented 2 years ago

Sounds like a good idea, i try to do the changes and come back but not sure when i got the time.

RickardPettersson commented 2 years ago

Added two properties on the Certificate object:

When UseMachineKeySet is true its only using the CertificateStream property to get the certificate.

Latest code uploaded and new nuget is on the way.

The SecureClient is Azure specific and i dont like to add that so this maybe can let you use SecureClient outside my class library and load it to stream.