syntax = "proto3";
package specs;

option go_package = "github.com/siderolabs/omni/client/api/omni/specs";

import "talos/machine/machine.proto";
import "google/protobuf/timestamp.proto";

// AuthConfigSpec describes the authentication configuration.
message AuthConfigSpec {
  message Auth0 {
    bool enabled = 1;
    string domain = 2;
    string client_id = 3;
    bool useFormData = 4;
  }

  message OIDC {
    bool enabled = 1;
    string provider_url = 2;
    string client_id = 3;
    string client_secret = 4;
    repeated string scopes = 5;
  }

  message Webauthn {
    bool enabled = 1;
    bool required = 2;
  }

  message SAML {
    bool enabled = 1;
    string url = 2;
    string metadata = 3;
    // LabelRules defines custom rules on how to extract SAML attributes from the
    // saml assertion and turn them into labels.
    map<string, string> label_rules = 4;
    string name_id_format = 5;
    // AttributeRules defines custom rules on how to extract the identity, fullname, firstname and lastname
    // from the SAML assertion.
    map<string, string> attribute_rules = 6;
  }

  Auth0 auth0 = 1;
  Webauthn webauthn = 2;
  bool suspended = 3;
  SAML saml = 4;
  OIDC oidc = 5;
}

// SAMLAssertionSpec describes SAML assertion.
message SAMLAssertionSpec {
  // Data keeps JSON encoded SAML assertion.
  bytes data = 1;

  // Email is the identity that was read from the assertion.
  string email = 2;

  // Used marks SAML assertion as used.
  bool used = 3;
}

// UserSpec describes a user.
message UserSpec {
  reserved 1;
  // Scopes are deprecated, use roles instead.
  //
  // Deprecated: will be removed once all environments are migrated to use roles.
  // TODO: remove after all environments are migrated to use roles.
  repeated string scopes = 2;
  string role = 3;
}

// IdentitySpec describes a user identity.
message IdentitySpec {
  string user_id = 1;
}

message Identity {
  string email = 1;
}

// PublicKeySpec describes a user or service account public key.
message PublicKeySpec {
  enum Type {
    UNKNOWN = 0;
    PGP = 1;
    PLAIN = 2;
  }

  bytes public_key = 1;
  // Scopes are deprecated, use roles instead.
  //
  // Deprecated: will be removed once all environments are migrated to use roles.
  // TODO: remove after all environments are migrated to use roles.
  repeated string scopes = 2;
  google.protobuf.Timestamp expiration = 3;
  bool confirmed = 4;
  Identity identity = 5;
  string role = 6;
  Type type = 7;
}

// AccessPolicyUserGroup describes a user group in the ACLs context.
message AccessPolicyUserGroup {
  message User {
    string name = 1;
    string match = 2;
    repeated string label_selectors = 3;
  }

  repeated User users = 1;
}

// AccessPolicyClusterGroup describes a cluster group in the ACLs context.
message AccessPolicyClusterGroup {
  message Cluster {
    string name = 1;
    string match = 2;
  }

  repeated Cluster clusters = 1;
}

// AccessPolicyRule describes a rule in the ACLs context.
message AccessPolicyRule {
  message Kubernetes {
    message Impersonate {
      repeated string groups = 1;
    }

    Impersonate impersonate = 1;
  }

  repeated string users = 1;
  repeated string clusters = 2;
  Kubernetes kubernetes = 3;
  string role = 4;
}

message AccessPolicyTest {
  message Expected {
    message Kubernetes {
      message Impersonate {
        repeated string groups = 1;
      }

      Impersonate impersonate = 1;
    }

    Kubernetes kubernetes = 1;
    string role = 2;
  }

  message User {
    string name = 1;
    map<string, string> labels = 2;
  }

  message Cluster {
    string name = 1;
  }

  string name = 1;
  User user = 2;
  Cluster cluster = 3;
  Expected expected = 4;
}

// AccessPolicySpec describes the access policy configuration.
message AccessPolicySpec {
   map<string, AccessPolicyUserGroup> user_groups = 1;
   map<string, AccessPolicyClusterGroup> cluster_groups = 2;
   repeated AccessPolicyRule rules = 3;
   repeated AccessPolicyTest tests = 4;
}

// SAMLLabelRuleSpec describes a rule on how to map Identity labels to Omni roles.
//
message SAMLLabelRuleSpec {
  // MatchLabels is the list of labels to match the user's Identity against this rule.
  repeated string match_labels = 1;

  // AssignRoleOnRegistration is the role to be assigned to the user if this rule matches.
  //
  // Deprecated: use AssignRole instead.
  string assign_role_on_registration = 2;

  // AssignRole to the user matched by this rule.
  string assign_role = 3;

  // UpdateOnEachLogin makes the rule to be applied every time user logs in.
  bool update_on_each_login = 4;
}

// IdentityLastActiveSpec tracks the last time a user or service account was active.
message IdentityLastActiveSpec {
  google.protobuf.Timestamp last_active = 1;
}

// IdentityStatusSpec aggregates identity, user, and activity data into a single resource.
message IdentityStatusSpec {
  string user_id = 1;
  string role = 2;
  string last_active = 3;
}

message ServiceAccountStatusSpec {
  message PgpPublicKey {
    string id = 1;
    string armored = 2;
    google.protobuf.Timestamp expiration = 3;
  }

  string role = 1;

  repeated PgpPublicKey public_keys = 2;
}

// EulaAcceptanceSpec records the instance-wide EULA acceptance.
message EulaAcceptanceSpec {
  // AcceptedByName is the full name of the person who accepted the EULA.
  string accepted_by_name = 1;

  // AcceptedByEmail is the email address of the person who accepted the EULA.
  string accepted_by_email = 2;
}
