-
-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathmod.rs
More file actions
178 lines (156 loc) · 7.47 KB
/
mod.rs
File metadata and controls
178 lines (156 loc) · 7.47 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[cfg(doc)]
use url::Url;
use crate::{
commons::{networking::HostName, tls_verification::TlsClientDetails},
versioned::versioned,
};
mod v1alpha1_impl;
// FIXME (@Techassi): These constants should also be versioned
pub const CLIENT_ID_SECRET_KEY: &str = "clientId";
pub const CLIENT_SECRET_SECRET_KEY: &str = "clientSecret";
/// Do *not* use this for [`Url::join`], as the leading slash will erase the existing path!
const DEFAULT_WELLKNOWN_OIDC_CONFIG_PATH: &str = "/.well-known/openid-configuration";
#[versioned(version(name = "v1alpha1"))]
pub mod versioned {
pub mod v1alpha1 {
// Re-export the v1alpha1-specific error type from the private impl module.
pub use v1alpha1_impl::Error;
}
/// This struct contains configuration values to configure an OpenID Connect
/// (OIDC) authentication class. Required fields are the identity provider
/// (IdP) `hostname` and the TLS configuration. The `port` is selected
/// automatically if not configured otherwise. The `rootPath` defaults
/// to `/`.
#[derive(
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationProvider {
/// Host of the identity provider, e.g. `my.keycloak.corp` or `127.0.0.1`.
hostname: HostName,
/// Port of the identity provider. If TLS is used defaults to 443,
/// otherwise to 80.
port: Option<u16>,
/// Root HTTP path of the identity provider. Defaults to `/`.
#[serde(default = "v1alpha1::AuthenticationProvider::default_root_path")]
root_path: String,
/// Use a TLS connection. If not specified no TLS will be used.
#[serde(flatten)]
pub tls: TlsClientDetails,
/// If a product extracts some sort of "effective user" that is represented by a
/// string internally, this config determines with claim is used to extract that
/// string. It is desirable to use `sub` in here (or some other stable identifier),
/// but in many cases you might need to use `preferred_username` (e.g. in case of Keycloak)
/// or a different claim instead.
///
/// Please note that some products hard-coded the claim in their implementation,
/// so some product operators might error out if the product hardcodes a different
/// claim than configured here.
///
/// We don't provide any default value, as there is no correct way of doing it
/// that works in all setups. Most demos will probably use `preferred_username`,
/// although `sub` being more desirable, but technically impossible with the current
/// behavior of the products.
pub principal_claim: String,
/// Scopes to request from your identity provider. It is recommended to
/// request the `openid`, `email`, and `profile` scopes.
pub scopes: Vec<String>,
/// This is a hint about which identity provider is used by the
/// AuthenticationClass. Operators *can* opt to use this
/// value to enable known quirks around OIDC / OAuth authentication.
/// Not providing a hint means there is no hint and OIDC should be used as it is
/// intended to be used (via the `.well-known` discovery).
#[serde(default)]
pub provider_hint: Option<IdentityProviderHint>,
}
/// An enum of supported OIDC or identity providers which can serve as a hint
/// in the product operator. Some products require special handling of
/// authentication related config options. This hint can be used to enable such
/// special handling.
#[derive(
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
)]
#[serde(rename_all = "PascalCase")]
pub enum IdentityProviderHint {
Keycloak,
}
/// OAuth2 client authentication methods as defined in the OpenID Connect Core spec.
///
/// These methods are used by clients to authenticate to the authorization server
/// when using the token endpoint.
///
/// See <https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication> for details.
#[derive(
Clone,
Copy,
Debug,
Default,
Deserialize,
Eq,
Hash,
JsonSchema,
Ord,
PartialEq,
PartialOrd,
Serialize,
)]
#[serde(rename_all = "snake_case")]
pub enum ClientAuthenticationMethod {
/// Authenticate using HTTP Basic authentication with client_id and client_secret.
/// This is the default method according to the OIDC spec.
#[default]
ClientSecretBasic,
/// Send client_id and client_secret in the request body.
ClientSecretPost,
/// Authenticate using a JWT signed with an HMAC SHA algorithm using the client_secret.
ClientSecretJwt,
/// Authenticate using a JWT signed with the client's private key.
PrivateKeyJwt,
/// No client authentication (for public clients or implicit flow).
None,
}
/// OIDC specific config options. These are set on the product config level.
#[derive(
Clone, Debug, Deserialize, Eq, Hash, JsonSchema, Ord, PartialEq, PartialOrd, Serialize,
)]
#[serde(rename_all = "camelCase")]
pub struct ClientAuthenticationOptions<T = ()> {
/// A reference to the OIDC client credentials secret. The secret contains
/// the client id and secret.
#[serde(rename = "clientCredentialsSecret")]
pub client_credentials_secret_ref: String,
/// An optional list of extra scopes which get merged with the scopes
/// defined in the [`AuthenticationClass`][1].
///
/// [1]: crate::crd::authentication::core::v1alpha1::AuthenticationClass
#[schemars(
description = "An optional list of extra scopes which get merged with the scopes defined in the AuthenticationClass"
)]
#[serde(default)]
pub extra_scopes: Vec<String>,
/// The OAuth2 client authentication method to use for token endpoint requests.
/// Defaults to [`ClientAuthenticationMethod::ClientSecretBasic`].
///
/// The contents and format of the `clientCredentialsSecret` depend on the selected
/// method. For example, [`ClientAuthenticationMethod::ClientSecretBasic`] and
/// [`ClientAuthenticationMethod::ClientSecretPost`] require a client secret string, whereas
/// [`ClientAuthenticationMethod::PrivateKeyJwt`] requires a private key.
///
/// See [`ClientAuthenticationMethod`] for available options.
#[schemars(
description = "The client authentication method used when communicating with the token \
endpoint. Defaults to `client_secret_basic`. The required contents of \
`clientCredentialsSecret` depend on the chosen method: secret-based methods \
(`client_secret_basic`, `client_secret_post`, `client_secret_jwt`) expect a client \
secret, while `private_key_jwt` expects a private key."
)]
#[serde(default)]
pub client_authentication_method: ClientAuthenticationMethod,
// If desired, operators can add custom fields that are only needed for this specific product.
// They need to create a struct holding them and pass that as `T`.
#[serde(flatten)]
pub product_specific_fields: T,
}
}