aboutsummaryrefslogtreecommitdiff
path: root/lib/VNLib.Data.Caching.Extensions/src/ClientCacheConfiguration.cs
blob: ef44a29313ec377d39fb764f56438d44c9081d7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* Copyright (c) 2023 Vaughn Nugent
* 
* Library: VNLib
* Package: VNLib.Data.Caching.Extensions
* File: ClientCacheConfiguration.cs 
*
* ClientCacheConfiguration.cs is part of VNLib.Data.Caching.Extensions which is part of the larger 
* VNLib collection of libraries and utilities.
*
* VNLib.Data.Caching.Extensions is free software: you can redistribute it and/or modify 
* it under the terms of the GNU Affero General Public License as 
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* VNLib.Data.Caching.Extensions is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see https://www.gnu.org/licenses/.
*/

using System;
using System.Collections.Generic;
using System.Security.Cryptography;

using VNLib.Hashing;
using VNLib.Hashing.IdentityUtility;

namespace VNLib.Data.Caching.Extensions
{
    /// <summary>
    /// A fluent api configuration object for configuring a <see cref="FBMClient"/>
    /// to connect to cache servers.
    /// </summary>
    public sealed class ClientCacheConfiguration
    {
        internal ReadOnlyJsonWebKey? SigningKey { get; private set; }
        internal ReadOnlyJsonWebKey? VerificationKey { get; private set; }
        internal ReadOnlyJsonWebKey? BrokerVerificationKey { get; private set; }
        
        internal string ServerChallenge { get; } = RandomHash.GetRandomBase32(24);
        internal string? NodeId { get; set; }
        internal Uri? BrokerAddress { get; set; }
        internal bool UseTls { get; set; }
        internal ActiveServer[]? CacheServers { get; set; }

        internal IReadOnlyDictionary<string, string?> JwtHeader => SigningKey!.JwtHeader;

        /// <summary>
        /// Imports the private key used to sign messages
        /// </summary>
        /// <param name="jwk">The <see cref="ReadOnlyJsonWebKey"/> with a private key loaded</param>
        /// <returns>Chainable fluent object</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="CryptographicException"></exception>
        public ClientCacheConfiguration WithSigningCertificate(ReadOnlyJsonWebKey jwk)
        {
            SigningKey = jwk ?? throw new ArgumentNullException(nameof(jwk));
            return this;
        }

        /// <summary>
        /// Imports the public key used to verify messages from the remote server
        /// </summary>
        /// <param name="jwk">The <see cref="ReadOnlyJsonWebKey"/> public key only used for message verification</param>
        /// <returns>Chainable fluent object</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="CryptographicException"></exception>
        public ClientCacheConfiguration WithVerificationKey(ReadOnlyJsonWebKey jwk)
        {
            VerificationKey = jwk ?? throw new ArgumentNullException(nameof(jwk));
            return this;
        }

        public ClientCacheConfiguration WithBrokerVerificationKey(ReadOnlyJsonWebKey jwk)
        {
            BrokerVerificationKey = jwk ?? throw new ArgumentNullException(nameof(jwk));
            return this;
        }

        /// <summary>
        /// Specifies if all connections should be using TLS
        /// </summary>
        /// <param name="useTls">A value that indicates if connections should use TLS</param>
        /// <returns>Chainable fluent object</returns>
        public ClientCacheConfiguration WithTls(bool useTls)
        {
            UseTls = useTls;
            return this;   
        }
        /// <summary>
        /// Specifies the broker address to discover cache nodes from
        /// </summary>
        /// <param name="brokerAddress">The address of the server broker</param>
        /// <returns>Chainable fluent object</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public ClientCacheConfiguration WithBroker(Uri brokerAddress)
        {
            this.BrokerAddress = brokerAddress ?? throw new ArgumentNullException(nameof(brokerAddress));
            return this;
        }

        /// <summary>
        /// Specifies the current server's cluster node id. If this 
        /// is a server connection attempting to listen for changes on the
        /// remote server, this id must be set and unique
        /// </summary>
        /// <param name="nodeId">The cluster node id of the current server</param>
        /// <returns>Chainable fluent object</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public ClientCacheConfiguration WithNodeId(string nodeId)
        {
            this.NodeId = nodeId ?? throw new ArgumentNullException(nameof(nodeId));
            return this;
        }

        internal void SignJwt(JsonWebToken jwt)
        {
            jwt.SignFromJwk(SigningKey);
        }

        internal bool VerifyCache(JsonWebToken jwt)
        {
            return jwt.VerifyFromJwk(VerificationKey);
        }

        internal bool VerifyBroker(JsonWebToken jwt)
        {
            return jwt.VerifyFromJwk(BrokerVerificationKey);
        }
    }
}