masks-server 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/masks/server/discovery_controller.rb +36 -0
  3. data/app/controllers/masks/server/enrollments_controller.rb +17 -0
  4. data/app/controllers/masks/server/organization_members_controller.rb +3 -1
  5. data/app/graphql/masks/server/manage/mutations/unenroll_client.rb +28 -0
  6. data/app/graphql/masks/server/manage/types/client_type.rb +6 -0
  7. data/app/graphql/masks/server/manage/types/mutation_type.rb +1 -0
  8. data/app/jobs/masks/server/application_job.rb +28 -0
  9. data/app/jobs/masks/server/check_domain_claims_job.rb +1 -3
  10. data/app/jobs/masks/server/cleanup_job.rb +4 -6
  11. data/app/jobs/masks/server/idle_accounts_job.rb +1 -3
  12. data/app/jobs/masks/server/prune_queue_job.rb +19 -0
  13. data/app/jobs/masks/server/refresh_saml_metadata_job.rb +1 -3
  14. data/app/jobs/masks/server/rotate_signing_keys_job.rb +1 -3
  15. data/app/jobs/masks/server/text_job.rb +12 -1
  16. data/app/models/masks/server/app_preset.rb +102 -0
  17. data/app/models/masks/server/boot_task.rb +41 -0
  18. data/app/models/masks/server/enrollment_token.rb +1 -1
  19. data/app/models/masks/server/event.rb +5 -1
  20. data/app/models/masks/server/job_failures.rb +25 -0
  21. data/config/locales/de/events.yml +4 -0
  22. data/config/locales/de/manage/client.yml +1 -1
  23. data/config/locales/de/manage/machines.yml +13 -0
  24. data/config/locales/de/manage/namespaces.yml +1 -1
  25. data/config/locales/en/events.yml +4 -0
  26. data/config/locales/en/manage/machines.yml +13 -0
  27. data/config/locales/es/events.yml +4 -0
  28. data/config/locales/es/handshakes.yml +1 -1
  29. data/config/locales/es/manage/machines.yml +13 -0
  30. data/config/locales/fr/events.yml +4 -0
  31. data/config/locales/fr/handshakes.yml +1 -1
  32. data/config/locales/fr/manage/client.yml +1 -1
  33. data/config/locales/fr/manage/clients.yml +1 -1
  34. data/config/locales/fr/manage/machines.yml +13 -0
  35. data/config/locales/fr/manage/providers.yml +1 -1
  36. data/config/routes.rb +1 -0
  37. data/db/migrate/20261019140000_add_indexes_for_cleanup_and_metrics.rb +10 -0
  38. data/lib/masks/server/configuration.rb +4 -0
  39. data/lib/tasks/masks.rake +31 -7
  40. data/public/masks-assets/.vite/manifest.json +1 -1
  41. data/public/masks-assets/assets/{manage-DR9qQiBU.js → manage-D4MzaDvM.js} +33 -26
  42. data/public/masks-assets/assets/manage-D4MzaDvM.js.map +1 -0
  43. data/version.txt +1 -1
  44. metadata +12 -3
  45. data/public/masks-assets/assets/manage-DR9qQiBU.js.map +0 -1
@@ -157,6 +157,8 @@ fr:
157
157
  exported: "Activité exportée"
158
158
  mail_template:
159
159
  updated: "Modèle d’e-mail modifié"
160
+ job:
161
+ failed: "Tâche de fond échouée pour ce locataire"
160
162
  stream:
161
163
  created: "Flux d’événements ajouté"
162
164
  updated: "Flux d’événements modifié"
@@ -171,6 +173,8 @@ fr:
171
173
  signal:
172
174
  undelivered: "Signal partagé non transmis"
173
175
  received: "Déconnexion signalée par un fournisseur"
176
+ text:
177
+ undelivered: "SMS non transmis"
174
178
  organization:
175
179
  created: "Organisation ajoutée"
176
180
  updated: "Organisation modifiée"
@@ -26,7 +26,7 @@ fr:
26
26
  area_yours: " Vous les recevez toutes dès maintenant."
27
27
  also: "%{name} peut aussi"
28
28
  details: "Détails techniques"
29
- scopes: "Scopes"
29
+ scopes: "Portées"
30
30
  client: "Identifiants"
31
31
  credentials:
32
32
  public: "Publique. Elle ne détient aucun secret."
@@ -173,7 +173,7 @@ fr:
173
173
  on_request: "Sur demande"
174
174
  uris:
175
175
  title: "URI"
176
- acs: "Assertion consumer services"
176
+ acs: "Services consommateurs d'assertions"
177
177
  redirect: "Redirection"
178
178
  post_logout: "Redirection post-déconnexion"
179
179
  resources: "Ressources"
@@ -30,7 +30,7 @@ fr:
30
30
  metadata: "Ses métadonnées"
31
31
  read: "Les lire"
32
32
  entity_id: "Entity ID"
33
- acs: "Assertion consumer services"
33
+ acs: "Services consommateurs d'assertions"
34
34
  certificate: "Certificat de signature, s’il signe ses requêtes"
35
35
  requests_signed: "Refuser les requêtes qu’il n’a pas signées"
36
36
  slo_url: "URL de déconnexion unique, s’il en a une"
@@ -0,0 +1,13 @@
1
+ fr:
2
+ manage:
3
+ machines:
4
+ title: "Machines"
5
+ lede: "Clients que cette application a inscrits avec un jeton d'inscription. Chacun se connecte avec sa propre clé."
6
+ empty: "Cette application n'a pas encore inscrit de machine."
7
+ last_seen: "Dernière connexion %{day}"
8
+ never: "Jamais connectée"
9
+ enrolled: "Inscrite %{day}"
10
+ enrolled_by: "Une machine inscrite par"
11
+ revoke: "Révoquer"
12
+ revoke_confirm: "Révoquer %{name} ? Elle est archivée, chaque jeton prend fin et elle ne peut plus se connecter."
13
+ revoked: "%{name} est révoquée et ne peut plus se connecter."
@@ -77,7 +77,7 @@ fr:
77
77
  credentials: "Identifiants"
78
78
  services_id: "Services ID"
79
79
  client_id: "Client ID"
80
- client_secret: "Client secret"
80
+ client_secret: "Secret du client"
81
81
  unchanged: "inchangé"
82
82
  team_id: "Team ID"
83
83
  key_id: "Key ID"
data/config/routes.rb CHANGED
@@ -4,6 +4,7 @@ Masks::Server::Engine.routes.draw do
4
4
  get "/.well-known/jwks.json", to: "discovery#jwks"
5
5
  get "/.well-known/oauth-protected-resource(/*resource)", to: "discovery#resource"
6
6
  get "/.well-known/ssf-configuration", to: "signal_streams#configuration"
7
+ get "/.well-known/webfinger", to: "discovery#webfinger"
7
8
 
8
9
  scope "/ssf", controller: :signal_streams, defaults: { format: :json } do
9
10
  get "/streams", action: :show
@@ -0,0 +1,10 @@
1
+ class AddIndexesForCleanupAndMetrics < ActiveRecord::Migration[8.1]
2
+ def change
3
+ add_index :sessions, %i[tenant_id expires_at]
4
+ add_index :sessions, %i[tenant_id revoked_at], where: "revoked_at IS NOT NULL"
5
+ add_index :sessions, %i[tenant_id created_at]
6
+ add_index :tokens, %i[tenant_id kind created_at]
7
+ add_index :tokens, "tenant_id, LEAST(consumed_at, expires_at)", name: "index_tokens_on_tenant_id_and_ended_at"
8
+ add_index :signing_keys, %i[tenant_id retired_at], where: "retired_at IS NOT NULL"
9
+ end
10
+ end
@@ -46,6 +46,10 @@ module Masks
46
46
  config.ldap_cert = ENV["MASKS_LDAP_CERT"].presence
47
47
  config.ldap_key = ENV["MASKS_LDAP_KEY"].presence
48
48
  config.ldap_plaintext = ENV.fetch("MASKS_LDAP_PLAINTEXT", "false") == "true"
49
+ config.worker_silence = ENV.fetch("MASKS_WORKER_SILENCE", 300).to_i.seconds
50
+ config.queue_wait = ENV.fetch("MASKS_QUEUE_WAIT", 600).to_i.seconds
51
+ config.finished_job_retention = ENV.fetch("MASKS_FINISHED_JOB_RETENTION", 7 * 24 * 60 * 60).to_i.seconds
52
+ config.failed_job_retention = ENV.fetch("MASKS_FAILED_JOB_RETENTION", 30 * 24 * 60 * 60).to_i.seconds
49
53
  config
50
54
  end
51
55
 
data/lib/tasks/masks.rake CHANGED
@@ -3,20 +3,44 @@ namespace :masks do
3
3
  task tenants: :environment do
4
4
  Masks::Server::MasterKey.check!
5
5
 
6
- Masks::Server::Tenant.declare!.each { |tenant| puts "#{tenant.subdomain}: #{tenant.signing_key.kid}" }
6
+ config = Rails.configuration.masks
7
+ announce = lambda do |outcome, lines|
8
+ if outcome.done?
9
+ lines.call(outcome.value).each { |line| puts "masks: #{line}" }
10
+ puts "masks: #{outcome.name} done on #{outcome.host}"
11
+ else
12
+ puts "masks: #{outcome.name} already done on #{outcome.host}, skipped"
13
+ end
14
+ end
15
+
16
+ declared = Masks::Server::BootTask.once("tenants", fingerprint: config.tenants.join(",")) { Masks::Server::Tenant.declare! }
17
+ announce.call(declared, ->(tenants) { tenants.map { |tenant| "#{tenant.subdomain}: #{tenant.signing_key.kid}" } })
7
18
 
8
19
  Masks::Server::Tenant.active.reject(&:set_up?).each { |tenant| puts "masks: #{tenant.setup_announcement}" }
9
20
 
10
- Masks::Server::Declared.apply!.each { |said| puts "masks: #{said}" }
21
+ if config.config_path.present?
22
+ digest = File.exist?(config.config_path) ? Digest::SHA256.file(config.config_path).hexdigest : config.config_path
23
+ applied = Masks::Server::BootTask.once("config", fingerprint: digest) { Masks::Server::Declared.apply! }
24
+ announce.call(applied, ->(said) { said })
25
+ end
11
26
 
12
- Masks::Server::LockedOut.recover!.each { |recovered| puts "masks: #{recovered}" }
27
+ if config.recover.present?
28
+ recovered = Masks::Server::BootTask.once("recover", fingerprint: config.recover) { Masks::Server::LockedOut.recover! }
29
+ announce.call(recovered, ->(lines) { lines })
30
+ end
13
31
 
14
32
  if ENV["ENCRYPTION_PREVIOUS_PRIMARY_KEY"].present?
15
- Masks::Server::MasterKey.reencrypt!
16
- puts "masks: every encrypted column now uses the current master key. Remove MASKS_PREVIOUS_MASTER_KEY."
33
+ reencrypted = Masks::Server::BootTask.once("reencrypt", fingerprint: ENV["ENCRYPTION_PREVIOUS_PRIMARY_KEY"]) do
34
+ Masks::Server::MasterKey.reencrypt!
35
+ [ "every encrypted column now uses the current master key. Remove MASKS_PREVIOUS_MASTER_KEY." ]
36
+ end
37
+ announce.call(reencrypted, ->(lines) { lines })
17
38
  elsif Masks::Server::MasterKey.underived.exists?
18
- Masks::Server::MasterKey.reencrypt!(Masks::Server::MasterKey.underived)
19
- puts "masks: every tenant's encrypted columns now use a key of that tenant's own."
39
+ derived = Masks::Server::BootTask.once("derive", fingerprint: Masks::Server::MasterKey.underived.pluck(:id).sort.join(",")) do
40
+ Masks::Server::MasterKey.reencrypt!(Masks::Server::MasterKey.underived)
41
+ [ "every tenant's encrypted columns now use a key of that tenant's own." ]
42
+ end
43
+ announce.call(derived, ->(lines) { lines })
20
44
  end
21
45
  end
22
46
  end
@@ -51,7 +51,7 @@
51
51
  ]
52
52
  },
53
53
  "entrypoints/manage.js": {
54
- "file": "assets/manage-DR9qQiBU.js",
54
+ "file": "assets/manage-D4MzaDvM.js",
55
55
  "name": "entrypoints/manage.js",
56
56
  "src": "entrypoints/manage.js",
57
57
  "isEntry": true,