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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
// A note on users
//
// Internally, in Pachyderm, usernames are structured strings. This makes both
// our API and our data model more flexible (at the loss of some type safety).
// Basically, anywhere that Pachyderm internally stores a subject (i.e.
// TokenInfo) or principal (ACL, the 'admins' collection), that username will
// have some structured prefix.
//
// Note that externally-facing principals ({Get,Set}{Scope,ACL}, ModifyAdmins,
// ListAdmins) will have their own conventions
//
// The current user formats are:
// 1) GitHub usernames:
//      "github:MyGitHubUsername"
// 2) Pachyderm robot users:
//      "robot:robot_user_1"
// 3) Pachyderm pipelines:
//      "pipeline:terasort"

//// Activation API

/// ActivateRequest mirrors AuthenticateRequest. The caller is authenticated via
/// GitHub OAuth, and then promoted to the cluster's first Admin. Afterwards, the
/// caller can promote other users to Admin and remove themselves
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ActivateRequest {
    /// If set, Pachyderm will authenticate the caller as this user.
    /// - If set to a github user (i.e. it has a 'github:' prefix or no prefix)
    ///   then Pachyderm will confirm that it matches the user associated with
    ///   'github_token'
    /// - If set to a robot user (i.e. it has a 'robot:' prefix), then Pachyderm
    ///   will generate a new token for the robot user; this token will be the only
    ///   way to administer this cluster until more admins are added.
    #[prost(string, tag="2")]
    pub subject: std::string::String,
    /// This is the token returned by GitHub and used to authenticate the caller.
    /// When Pachyderm is deployed locally, setting this value to a given string
    /// will automatically authenticate the caller as a GitHub user whose username
    /// is that string (unless this "looks like" a GitHub access code, in which
    /// case Pachyderm does retrieve the corresponding GitHub username)
    #[prost(string, tag="1")]
    pub github_token: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ActivateResponse {
    /// pach_token authenticates the caller with Pachyderm (if you want to perform
    /// Pachyderm operations after auth has been activated as themselves, you must
    /// present this token along with your regular request)
    #[prost(string, tag="1")]
    pub pach_token: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct DeactivateRequest {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct DeactivateResponse {
}
/// IDProvider configures a single ID provider that can authenticate Pachyderm
/// users
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct IdProvider {
    /// Name identifies this authentication backend in Pachyderm.
    #[prost(string, tag="1")]
    pub name: std::string::String,
    /// Description is a human-readable description of this authentication
    /// backend. It's ignored by Pachyderm, but exists for the benefit of users
    /// configuring Pachyderm's auth system.
    #[prost(string, tag="2")]
    pub description: std::string::String,
    #[prost(message, optional, tag="3")]
    pub saml: ::std::option::Option<id_provider::SamlOptions>,
    #[prost(message, optional, tag="5")]
    pub oidc: ::std::option::Option<id_provider::OidcOptions>,
    #[prost(message, optional, tag="4")]
    pub github: ::std::option::Option<id_provider::GitHubOptions>,
}
pub mod id_provider {
    /// SAMLOptions describes a SAML-based identity provider
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct SamlOptions {
        /// metadata_url is the URL of the SAML ID provider's metadata service
        /// (which Pachd can query to get more info about the SAML ID provider)
        #[prost(string, tag="1")]
        pub metadata_url: std::string::String,
        /// metadata_xml is a direct reproduction of the ID provider's metadata.
        /// Users can set this field in the argument to SetConfig if the ID provider
        /// can't be reached from pachd (e.g. because it's on a separate network to
        /// which Pachyderm users also have access) or for testing.  Exactly one of
        /// metadata_url and metadata_xml should be set in calls to SetConfig, but
        /// internally, if metadata_url is set, the result of scraping the metadata
        /// URL will be placed here in the result from GetConfig().
        #[prost(bytes, tag="2")]
        pub metadata_xml: std::vec::Vec<u8>,
        /// If this ID provider supports sending group memberships via attribute,
        /// then users can set group_attribute to the SAML attribute that indicates
        /// group mmbership, and Pachyderm will update users' group memberships when
        /// they authenticate.
        #[prost(string, tag="3")]
        pub group_attribute: std::string::String,
    }
    /// OIDCOptions describes a OIDC-based identity provider
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct OidcOptions {
        #[prost(string, tag="1")]
        pub issuer: std::string::String,
        #[prost(string, tag="2")]
        pub client_id: std::string::String,
        #[prost(string, tag="3")]
        pub client_secret: std::string::String,
        #[prost(string, tag="4")]
        pub redirect_uri: std::string::String,
    }
    /// GitHubOptions is an empty protobuf message whose presence in the IDProvider
    /// of an AuthConfig indicates that GitHub auth should be enabled.
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct GitHubOptions {
    }
}
/// Configure Pachyderm's auth system (particularly authentication backends
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AuthConfig {
    /// live_config_version identifies the version of a given pachyderm cluster's
    /// current auth configuration; if a user tries to write an auth configuration
    /// where live_config_version doesn't match the version of the cluster's
    /// current config, the write will fail. This allows for safe
    /// read+modify+write config changes.
    #[prost(int64, tag="1")]
    pub live_config_version: i64,
    /// id_providers describes external ID providers that can authenticate
    /// Pachyderm users (e.g. GitHub, Okta, etc)
    #[prost(message, repeated, tag="2")]
    pub id_providers: ::std::vec::Vec<IdProvider>,
    #[prost(message, optional, tag="3")]
    pub saml_svc_options: ::std::option::Option<auth_config::SamlServiceOptions>,
}
pub mod auth_config {
    /// saml_svc_options configures the SAML services (Assertion Consumer Service
    /// and Metadata Service) that Pachd can export.
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct SamlServiceOptions {
        /// acs is the URL of Pachd's Assertion Consumer Service (i.e. where SAML ID
        /// providers can send SAMLResponses to Pachd). If Pachyderm is running in a
        /// private cluster, the cluster admin would be responsible for setting up a
        /// domain name/proxy to resolve to pachd:654/acs
        #[prost(string, tag="1")]
        pub acs_url: std::string::String,
        /// metadata_url is the public URL of Pachd's SAML metadata service (some
        /// SAML ID providers will query this for information about Pachyderm's SAML
        /// implementation and use it to idenfity Pachyderm as a service provider).
        /// If Pachyderm is running in a private cluster, the cluster admin would be
        /// responsible for creating this URL (which must resolve to
        /// pachd:654/saml/metadata)
        #[prost(string, tag="2")]
        pub metadata_url: std::string::String,
        /// dash_url is the public address of this cluster's Pachyderm
        /// dashboard, if one exists; this option determines where users will be
        /// redirected after successfully authenticating
        #[prost(string, tag="3")]
        pub dash_url: std::string::String,
        /// session_duration determines the duration of SAML-IdP-authenticated user
        /// sessions (specified as a Golang time duration, e.g. "24h" or "600m"). If
        /// unset, user sessions last 24 hours (a short default, as SAML assertions
        /// may contain group memberships that need to be refreshed)
        #[prost(string, tag="4")]
        pub session_duration: std::string::String,
        /// debug_logging determines whether pachd emits verbose logs (including
        /// SAML credentials) as it receives them, which may be helpful for
        /// debugging. This will probably not be present in any official releases.
        #[prost(bool, tag="5")]
        pub debug_logging: bool,
    }
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetConfigurationRequest {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetConfigurationResponse {
    #[prost(message, optional, tag="1")]
    pub configuration: ::std::option::Option<AuthConfig>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetConfigurationRequest {
    #[prost(message, optional, tag="1")]
    pub configuration: ::std::option::Option<AuthConfig>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetConfigurationResponse {
}
/// ClusterRoles reflects any cluster-wide permissions a principal has.
/// A principal can have multiple cluster roles.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ClusterRoles {
    #[prost(enumeration="ClusterRole", repeated, tag="1")]
    pub roles: ::std::vec::Vec<i32>,
}
/// Get the current set of principals and roles for the cluster
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetClusterRoleBindingsRequest {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetClusterRoleBindingsResponse {
    /// bindings contains a mapping of principals to cluster roles
    #[prost(map="string, message", tag="1")]
    pub bindings: ::std::collections::HashMap<std::string::String, ClusterRoles>,
}
/// Set cluster roles for the specified principal. Setting an empty list of roles
/// revokes any roles the principal has.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ModifyClusterRoleBindingRequest {
    #[prost(string, tag="1")]
    pub principal: std::string::String,
    #[prost(message, optional, tag="2")]
    pub roles: ::std::option::Option<ClusterRoles>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ModifyClusterRoleBindingResponse {
}
/// Deprecated. Get the list of cluster super admins.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetAdminsRequest {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetAdminsResponse {
    #[prost(string, repeated, tag="1")]
    pub admins: ::std::vec::Vec<std::string::String>,
}
/// Deprecated. Add and remove users from the set of cluster super admins.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ModifyAdminsRequest {
    #[prost(string, repeated, tag="1")]
    pub add: ::std::vec::Vec<std::string::String>,
    #[prost(string, repeated, tag="2")]
    pub remove: ::std::vec::Vec<std::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ModifyAdminsResponse {
}
//// Authentication data structures

/// OTPInfo is the analogue of 'TokenInfo' for Authentication Codes (short-lived,
/// one-time-use codes that are passed to the frontend and then exchanged for
/// longer-lived tokens)
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct OtpInfo {
    /// Subject (i.e. Pachyderm account) that a given OTP authenticates. This may
    /// be copied into the 'subject' field of a TokenInfo, and therefore has the
    /// same format, with the same prefixes.
    #[prost(string, tag="1")]
    pub subject: std::string::String,
    /// session_expiration indicates when the subject's session expires, a.k.a.
    /// when the Token to which this OTP converts expires (likely later than this
    /// OTP expires, but never earlier).
    #[prost(message, optional, tag="2")]
    pub session_expiration: ::std::option::Option<::prost_types::Timestamp>,
}
/// TokenInfo is the 'value' of an auth token 'key' in the 'tokens' collection
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TokenInfo {
    /// Subject (i.e. Pachyderm account) that a given token authorizes. Prefixed
    /// with "github:" or "robot:" to distinguish the two classes of
    /// Subject in Pachyderm
    #[prost(string, tag="1")]
    pub subject: std::string::String,
    #[prost(enumeration="token_info::TokenSource", tag="2")]
    pub source: i32,
}
pub mod token_info {
    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
    #[repr(i32)]
    pub enum TokenSource {
        Invalid = 0,
        /// returned by Authenticate()--non-revokeable
        Authenticate = 1,
        /// returned by GetToken()--revokeable.
        GetToken = 2,
    }
}
//// Authentication API

/// Exactly one of 'github_token', 'oidc_state', or 'one_time_password' must be set:
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AuthenticateRequest {
    /// This is the token returned by GitHub and used to authenticate the caller.
    /// When Pachyderm is deployed locally, setting this value to a given string
    /// will automatically authenticate the caller as a GitHub user whose username
    /// is that string (unless this "looks like" a GitHub access code, in which
    /// case Pachyderm does retrieve the corresponding GitHub username)
    #[prost(string, tag="1")]
    pub github_token: std::string::String,
    /// This is the session state that Pachyderm creates in order to keep track of
    /// information related to the current OIDC session.
    #[prost(string, tag="3")]
    pub oidc_state: std::string::String,
    /// This is a short-lived, one-time-use password generated by Pachyderm, for
    /// the purpose of propagating authentication to new clients (e.g. from the
    /// dash to pachd)
    #[prost(string, tag="2")]
    pub one_time_password: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AuthenticateResponse {
    /// pach_token authenticates the caller with Pachyderm (if you want to perform
    /// Pachyderm operations after auth has been activated as themselves, you must
    /// present this token along with your regular request)
    #[prost(string, tag="1")]
    pub pach_token: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct WhoAmIRequest {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct WhoAmIResponse {
    #[prost(string, tag="1")]
    pub username: std::string::String,
    #[prost(bool, tag="2")]
    pub is_admin: bool,
    #[prost(int64, tag="3")]
    pub ttl: i64,
    #[prost(message, optional, tag="4")]
    pub cluster_roles: ::std::option::Option<ClusterRoles>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Acl {
    /// principal -> scope. All principals are the default principal of a Pachyderm
    /// subject (i.e. all keys in this map are strings prefixed with either
    /// "github:" or "robot:", followed by the name of a GitHub user, all of whom
    /// are Pachyderm subjects, or a Pachyderm robot user)
    #[prost(map="string, enumeration(Scope)", tag="1")]
    pub entries: ::std::collections::HashMap<std::string::String, i32>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Users {
    #[prost(map="string, bool", tag="1")]
    pub usernames: ::std::collections::HashMap<std::string::String, bool>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Groups {
    #[prost(map="string, bool", tag="1")]
    pub groups: ::std::collections::HashMap<std::string::String, bool>,
}
//// Authorization API

#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AuthorizeRequest {
    /// repo is the object that the caller wants to access
    #[prost(string, tag="1")]
    pub repo: std::string::String,
    /// scope is the access level that the caller needs to perform an action
    #[prost(enumeration="Scope", tag="2")]
    pub scope: i32,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AuthorizeResponse {
    /// authorized is true if the caller has at least
    /// 'AuthorizeRequest.scope'-level access to 'AuthorizeRequest.repo', and false
    /// otherwise
    #[prost(bool, tag="1")]
    pub authorized: bool,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetScopeRequest {
    /// username is the principal (some of which belong to robots rather than
    /// users, but the name is preserved for now to provide compatibility with the
    /// pachyderm dash) whose access level is queried. To query the access level
    /// of a robot user, the caller must prefix username with "robot:". If
    /// 'username' has no prefix (i.e. no ":"), then it's assumed to be a github
    /// user's principal.
    #[prost(string, tag="1")]
    pub username: std::string::String,
    /// repos are the objects to which 'username's access level is being queried
    #[prost(string, repeated, tag="2")]
    pub repos: ::std::vec::Vec<std::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetScopeResponse {
    /// scopes (actually a "role"--see "Scope") are the access level that
    /// 'GetScopeRequest.username' has to each repo in 'GetScopeRequest.repos', in
    /// the same order that repos appeared in 'repos'.
    #[prost(enumeration="Scope", repeated, tag="1")]
    pub scopes: ::std::vec::Vec<i32>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetScopeRequest {
    /// username is the principal (some of which belong to robots rather than
    /// users, but the name is preserved for now to provide compatibility with the
    /// pachyderm dash) whose access is being granted/revoked. As with
    /// GetScopeRequest, to set the access level of a robot user, the caller must
    /// prefix username with "robot:". If 'username' has no prefix (i.e. no ":"),
    /// then it's assumed to be a github user's principal.
    #[prost(string, tag="1")]
    pub username: std::string::String,
    /// repo is the object to which access is being granted/revoked
    #[prost(string, tag="2")]
    pub repo: std::string::String,
    /// scope (actually a "role"--see "Scope") is the access level that the owner
    /// of 'principal' will now have
    #[prost(enumeration="Scope", tag="3")]
    pub scope: i32,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetScopeResponse {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetAclRequest {
    #[prost(string, tag="1")]
    pub repo: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AclEntry {
    /// username is the principal posessing this level of access to this ACL's
    /// repo (despite the name, this principal may be for a human github user or a
    /// pachyderm robot)
    #[prost(string, tag="1")]
    pub username: std::string::String,
    /// scope is the level of access that the owner of 'principal' has to this
    /// ACL's repo (actually a role in typical security terminology)
    #[prost(enumeration="Scope", tag="2")]
    pub scope: i32,
}
/// GetACLReponse contains the list of entries on a Pachyderm ACL.
///
/// To avoid migration pain with the Pachyderm dash the list of user principal
/// entries and robot principal entries are separate. This way, no prefix or
/// other disambiguating device is needed in 'entries' to separate user
/// principals from robot principals (which would confuse the dash). Instead,
/// the dash can simply ignore robot principals.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetAclResponse {
    /// entries contains all [user principal] -> [role] mappings. This is separate
    /// from robot_entries to avoid migration pain the Pachyderm dashboard
    #[prost(message, repeated, tag="1")]
    pub entries: ::std::vec::Vec<AclEntry>,
    /// robot_entries contains all [robot principal] -> [role] mappings. This is
    /// separate from entries to be unambiguous (all keys are robot principals, but
    /// have no prefixes) while avoiding migration pain in the Pachyderm dashboard.
    #[prost(message, repeated, tag="2")]
    pub robot_entries: ::std::vec::Vec<AclEntry>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetAclRequest {
    #[prost(string, tag="1")]
    pub repo: std::string::String,
    #[prost(message, repeated, tag="2")]
    pub entries: ::std::vec::Vec<AclEntry>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetAclResponse {
}
//////////////////////////////
//// OIDC Data Structures ////
//////////////////////////////

/// SessionInfo stores information associated with one OIDC authentication
/// session (i.e. a single instance of a single user logging in). Sessions are
/// short-lived and stored in the 'oidc-authns' collection, keyed by the OIDC
/// 'state' token (30-character CSPRNG-generated string). 'GetOIDCLogin'
/// generates and inserts entries, then /authorization-code/callback retrieves
/// an access token from the ID provider and uses it to retrive the caller's
/// email and store it in 'email', and finally Authorize() returns a Pachyderm
/// token identified with that email address as a subject in Pachyderm.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SessionInfo {
    /// nonce is used by /authorization-code/callback to validate session
    /// continuity with the IdP after a user has arrived there from GetOIDCLogin().
    /// This is a 30-character CSPRNG-generated string.
    #[prost(string, tag="1")]
    pub nonce: std::string::String,
    /// email contains the email adddress associated with a user in their OIDC ID
    /// provider. Currently users are identified with their email address rather
    /// than their OIDC subject identifier to make switching between OIDC ID
    /// providers easier for users, and to make user identities more easily
    /// comprehensible in Pachyderm. The OIDC spec doesn't require that users'
    /// emails be present or unique, but we think this will be preferable in
    /// practice.
    #[prost(string, tag="2")]
    pub email: std::string::String,
    /// conversion_err indicates whether an error was encountered while exchanging
    /// an auth code for an access token, or while obtaining a user's email (in
    /// /authorization-code/callback). Storing the error state here allows any
    /// sibling calls to Authenticate() (i.e. using the same OIDC state token) to
    /// notify their caller that an error has occurred. We avoid passing the caller
    /// any details of the error (which are logged by Pachyderm) to avoid giving
    /// information to a user who has network access to Pachyderm but not an
    /// account in the OIDC provider.
    #[prost(bool, tag="3")]
    pub conversion_err: bool,
}
//// OIDC API

#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetOidcLoginRequest {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetOidcLoginResponse {
    /// The login URL generated for the OIDC object
    #[prost(string, tag="1")]
    pub login_url: std::string::String,
    #[prost(string, tag="2")]
    pub state: std::string::String,
}
//// Token API (very limited -- for pipelines)

#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetAuthTokenRequest {
    /// The returned token will allow the caller to access resources as this
    /// subject
    #[prost(string, tag="1")]
    pub subject: std::string::String,
    /// ttl indicates the requested (approximate) remaining lifetime of this token,
    /// in seconds
    #[prost(int64, tag="2")]
    pub ttl: i64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetAuthTokenResponse {
    /// A canonicalized version of the subject in the request
    #[prost(string, tag="2")]
    pub subject: std::string::String,
    /// A new auth token for the user in 'GetAuthTokenRequest.Subject' token
    #[prost(string, tag="1")]
    pub token: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ExtendAuthTokenRequest {
    /// token indicates the Pachyderm token whose TTL is being extended
    #[prost(string, tag="1")]
    pub token: std::string::String,
    /// ttl indicates the new TTL of 'token' (if it's longer than the existing TTL)
    #[prost(int64, tag="2")]
    pub ttl: i64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ExtendAuthTokenResponse {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RevokeAuthTokenRequest {
    #[prost(string, tag="1")]
    pub token: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct RevokeAuthTokenResponse {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetGroupsForUserRequest {
    #[prost(string, tag="1")]
    pub username: std::string::String,
    #[prost(string, repeated, tag="2")]
    pub groups: ::std::vec::Vec<std::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetGroupsForUserResponse {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ModifyMembersRequest {
    #[prost(string, tag="1")]
    pub group: std::string::String,
    #[prost(string, repeated, tag="2")]
    pub add: ::std::vec::Vec<std::string::String>,
    #[prost(string, repeated, tag="3")]
    pub remove: ::std::vec::Vec<std::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ModifyMembersResponse {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetGroupsRequest {
    #[prost(string, tag="1")]
    pub username: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetGroupsResponse {
    #[prost(string, repeated, tag="1")]
    pub groups: ::std::vec::Vec<std::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetUsersRequest {
    #[prost(string, tag="1")]
    pub group: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetUsersResponse {
    #[prost(string, repeated, tag="1")]
    pub usernames: ::std::vec::Vec<std::string::String>,
}
/// GetOneTimePassword allows users to generate short-lived (~30s) tokens that
/// can be passed to Authenticate() (via AuthenticateRequest.one_time_password)
/// and exchanged for a longer-lived pachyderm token. This is more secure than
/// GetAuthToken, which produces long-lived authorization tokens.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetOneTimePasswordRequest {
    /// If the caller is an admin, GetOneTimePassword() can return a code for
    /// any user (useful for testing).
    /// If the caller is not an admin, GetOneTimePassword() will return an
    /// authentication code for the caller if username is unset or set to the
    /// caller's username (and will return an error otherwise)
    #[prost(string, tag="1")]
    pub subject: std::string::String,
    /// ttl indicates the requested (approximate) remaining lifetime of this token,
    /// in seconds
    #[prost(int64, tag="2")]
    pub ttl: i64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetOneTimePasswordResponse {
    /// 'code' is the string that must be presented in
    /// AuthenticateRequest.one_time_password to login as
    /// GetOneTimePasswordRequest.subject
    #[prost(string, tag="1")]
    pub code: std::string::String,
    /// expiration is the time at which the token in 'code' will expire
    #[prost(message, optional, tag="2")]
    pub otp_expiration: ::std::option::Option<::prost_types::Timestamp>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum ClusterRole {
    Undefined = 0,
    /// SUPER gives access to all APIs and owner on everything in PFS (previous just called admin)
    Super = 1,
    /// FS gives Owner on all repos in PFS but not access to manage other aspects of the cluster
    Fs = 2,
}
//// Authorization data structures

/// Scope (actually a "role" in canonical security nomenclature) represents a
/// rough level of access that a principal has to a repo
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum Scope {
    /// To remove a user's scope from a repo, set their scope to NONE
    None = 0,
    Reader = 1,
    Writer = 2,
    Owner = 3,
}
# [ doc = r" Generated client implementations." ] pub mod api_client { # ! [ allow ( unused_variables , dead_code , missing_docs ) ] use tonic :: codegen :: * ; pub struct ApiClient < T > { inner : tonic :: client :: Grpc < T > , } impl ApiClient < tonic :: transport :: Channel > { # [ doc = r" Attempt to create a new client by connecting to a given endpoint." ] pub async fn connect < D > ( dst : D ) -> Result < Self , tonic :: transport :: Error > where D : std :: convert :: TryInto < tonic :: transport :: Endpoint > , D :: Error : Into < StdError > , { let conn = tonic :: transport :: Endpoint :: new ( dst ) ? . connect ( ) . await ? ; Ok ( Self :: new ( conn ) ) } } impl < T > ApiClient < T > where T : tonic :: client :: GrpcService < tonic :: body :: BoxBody > , T :: ResponseBody : Body + HttpBody + Send + 'static , T :: Error : Into < StdError > , < T :: ResponseBody as HttpBody > :: Error : Into < StdError > + Send , { pub fn new ( inner : T ) -> Self { let inner = tonic :: client :: Grpc :: new ( inner ) ; Self { inner } } pub fn with_interceptor ( inner : T , interceptor : impl Into < tonic :: Interceptor > ) -> Self { let inner = tonic :: client :: Grpc :: with_interceptor ( inner , interceptor ) ; Self { inner } } # [ doc = " Activate/Deactivate the auth API. 'Activate' sets an initial set of admins" ] # [ doc = " for the Pachyderm cluster, and 'Deactivate' removes all ACLs, tokens, and" ] # [ doc = " admins from the Pachyderm cluster, making all data publicly accessable" ] pub async fn activate ( & mut self , request : impl tonic :: IntoRequest < super :: ActivateRequest > , ) -> Result < tonic :: Response < super :: ActivateResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/Activate" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn deactivate ( & mut self , request : impl tonic :: IntoRequest < super :: DeactivateRequest > , ) -> Result < tonic :: Response < super :: DeactivateResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/Deactivate" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_configuration ( & mut self , request : impl tonic :: IntoRequest < super :: GetConfigurationRequest > , ) -> Result < tonic :: Response < super :: GetConfigurationResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetConfiguration" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn set_configuration ( & mut self , request : impl tonic :: IntoRequest < super :: SetConfigurationRequest > , ) -> Result < tonic :: Response < super :: SetConfigurationResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/SetConfiguration" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } # [ doc = " Deprecated. GetAdmins returns the current list of cluster super admins" ] pub async fn get_admins ( & mut self , request : impl tonic :: IntoRequest < super :: GetAdminsRequest > , ) -> Result < tonic :: Response < super :: GetAdminsResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetAdmins" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } # [ doc = " Deprecated. ModifyAdmins adds or removes super admins from the cluster" ] pub async fn modify_admins ( & mut self , request : impl tonic :: IntoRequest < super :: ModifyAdminsRequest > , ) -> Result < tonic :: Response < super :: ModifyAdminsResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/ModifyAdmins" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } # [ doc = " GetClusterRoleBindings returns the current set of cluster role bindings" ] pub async fn get_cluster_role_bindings ( & mut self , request : impl tonic :: IntoRequest < super :: GetClusterRoleBindingsRequest > , ) -> Result < tonic :: Response < super :: GetClusterRoleBindingsResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetClusterRoleBindings" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } # [ doc = " ModifyAdmin sets the list of admin roles for a principal" ] pub async fn modify_cluster_role_binding ( & mut self , request : impl tonic :: IntoRequest < super :: ModifyClusterRoleBindingRequest > , ) -> Result < tonic :: Response < super :: ModifyClusterRoleBindingResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/ModifyClusterRoleBinding" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn authenticate ( & mut self , request : impl tonic :: IntoRequest < super :: AuthenticateRequest > , ) -> Result < tonic :: Response < super :: AuthenticateResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/Authenticate" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn authorize ( & mut self , request : impl tonic :: IntoRequest < super :: AuthorizeRequest > , ) -> Result < tonic :: Response < super :: AuthorizeResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/Authorize" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn who_am_i ( & mut self , request : impl tonic :: IntoRequest < super :: WhoAmIRequest > , ) -> Result < tonic :: Response < super :: WhoAmIResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/WhoAmI" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_scope ( & mut self , request : impl tonic :: IntoRequest < super :: GetScopeRequest > , ) -> Result < tonic :: Response < super :: GetScopeResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetScope" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn set_scope ( & mut self , request : impl tonic :: IntoRequest < super :: SetScopeRequest > , ) -> Result < tonic :: Response < super :: SetScopeResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/SetScope" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_acl ( & mut self , request : impl tonic :: IntoRequest < super :: GetAclRequest > , ) -> Result < tonic :: Response < super :: GetAclResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetACL" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn set_acl ( & mut self , request : impl tonic :: IntoRequest < super :: SetAclRequest > , ) -> Result < tonic :: Response < super :: SetAclResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/SetACL" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_oidc_login ( & mut self , request : impl tonic :: IntoRequest < super :: GetOidcLoginRequest > , ) -> Result < tonic :: Response < super :: GetOidcLoginResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetOIDCLogin" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_auth_token ( & mut self , request : impl tonic :: IntoRequest < super :: GetAuthTokenRequest > , ) -> Result < tonic :: Response < super :: GetAuthTokenResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetAuthToken" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn extend_auth_token ( & mut self , request : impl tonic :: IntoRequest < super :: ExtendAuthTokenRequest > , ) -> Result < tonic :: Response < super :: ExtendAuthTokenResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/ExtendAuthToken" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn revoke_auth_token ( & mut self , request : impl tonic :: IntoRequest < super :: RevokeAuthTokenRequest > , ) -> Result < tonic :: Response < super :: RevokeAuthTokenResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/RevokeAuthToken" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn set_groups_for_user ( & mut self , request : impl tonic :: IntoRequest < super :: SetGroupsForUserRequest > , ) -> Result < tonic :: Response < super :: SetGroupsForUserResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/SetGroupsForUser" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn modify_members ( & mut self , request : impl tonic :: IntoRequest < super :: ModifyMembersRequest > , ) -> Result < tonic :: Response < super :: ModifyMembersResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/ModifyMembers" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_groups ( & mut self , request : impl tonic :: IntoRequest < super :: GetGroupsRequest > , ) -> Result < tonic :: Response < super :: GetGroupsResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetGroups" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_users ( & mut self , request : impl tonic :: IntoRequest < super :: GetUsersRequest > , ) -> Result < tonic :: Response < super :: GetUsersResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetUsers" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } pub async fn get_one_time_password ( & mut self , request : impl tonic :: IntoRequest < super :: GetOneTimePasswordRequest > , ) -> Result < tonic :: Response < super :: GetOneTimePasswordResponse > , tonic :: Status > { self . inner . ready ( ) . await . map_err ( | e | { tonic :: Status :: new ( tonic :: Code :: Unknown , format ! ( "Service was not ready: {}" , e . into ( ) ) ) } ) ? ; let codec = tonic :: codec :: ProstCodec :: default ( ) ; let path = http :: uri :: PathAndQuery :: from_static ( "/auth.API/GetOneTimePassword" ) ; self . inner . unary ( request . into_request ( ) , path , codec ) . await } } impl < T : Clone > Clone for ApiClient < T > { fn clone ( & self ) -> Self { Self { inner : self . inner . clone ( ) , } } } impl < T > std :: fmt :: Debug for ApiClient < T > { fn fmt ( & self , f : & mut std :: fmt :: Formatter < '_ > ) -> std :: fmt :: Result { write ! ( f , "ApiClient {{ ... }}" ) } } }