Untitled

 avatar
unknown
csharp
a year ago
3.7 kB
5
Indexable
public static IServiceCollection Add1CDefectsService(this IServiceCollection services, Action<Defects1CServiceOptions> configureOptions)
{
    services.AddOptions<Defects1CServiceOptions>()
        .Configure(configureOptions)
        // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
        .Validate(x => x.Address != null, "Client address not provided")
        // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
        .Validate(x => x.Address == null || x.Address.IsAbsoluteUri, "Client address is invalid");

    services.AddSingleton(sp => 
    {
        var options = sp.GetRequiredService<IOptions<Defects1CServiceOptions>>().Value;

        if (options.CredentialType != AuthenticationOptions.AuthenticationType.Negotiate)
        {
            throw new InvalidOperationException($"Нельзя вызывать KerberosClient для авторизации {options.CredentialType}");
        }

        Console.WriteLine($"KeytabPath: {options.KeytabPath}");
        Console.WriteLine($"Login: {options.Login}");
        Console.WriteLine($"Password: {options.Password}");

        KerberosCredential credential;

        if (string.IsNullOrWhiteSpace(options.KeytabPath) || File.Exists(options.KeytabPath) == false)
        {
            if (string.IsNullOrWhiteSpace(options.Password))
            {
                throw new InvalidOperationException($"Для авторизации {options.CredentialType} должен существовать keytab или должен быть заполнен пароль");
            }

            credential = new KerberosPasswordCredential(options.Login, options.Password);
        }
        else
        {
            var keytabData = File.ReadAllBytes(options.KeytabPath);
            var keytab = new KeyTable(keytabData);

            credential = new KeytabCredential(options.Login, keytab);
        }

        var config = Krb5Config.Kdc(@"/etc/krb5.conf");
        var client = new KerberosClient(config);

        client.CacheServiceTickets = true;
        client.RenewTickets = true;
        client.CacheInMemory = true;
        client.Cache = new Krb5TicketCache("/tmp/local_krb5cc_0");

        client.Authenticate(credential).ConfigureAwait(false).GetAwaiter().GetResult();

        Console.WriteLine("Client Authenticated!");

        return client;
    });

    services.AddHttpClient<IDefects1CService, Defects1CServiceImpl>(ConfigureDefects1CClient);

    return services;
}

private static void ConfigureDefects1CClient(IServiceProvider sp, HttpClient client)
{
    var options = sp.GetRequiredService<IOptions<Defects1CServiceOptions>>().Value;

    client.BaseAddress = options.Address;

    if (options.CredentialType == AuthenticationOptions.AuthenticationType.Basic)
    {
        var byteArray = Encoding.ASCII.GetBytes($"{options.Login}:{options.Password}");
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

    } else if (options.CredentialType == AuthenticationOptions.AuthenticationType.Negotiate)
    {
        var kerberosClient = sp.GetRequiredService<KerberosClient>();

        var spn = $"HTTP/{options.Address.Host}";
        var ticket = kerberosClient.GetServiceTicket(spn).ConfigureAwait(false).GetAwaiter().GetResult();
        var byteArray = ticket.EncodeGssApi().ToArray();

        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Negotiate", Convert.ToBase64String(byteArray));
    }
    else
    {
        throw new NotSupportedException($"{options.CredentialType}");
    }
}
Editor is loading...
Leave a Comment