icfs 0.1.3 → 0.2.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/bin/icfs_demo_fcgi.rb +2 -0
  3. data/{bin/icfs_demo_ssl_gen.rb → devel/demo/ssl_gen.rb} +25 -13
  4. data/devel/demo/ssl_gen.yml +14 -0
  5. data/devel/icfs-wrk/Dockerfile +1 -1
  6. data/devel/run/base.rb +92 -0
  7. data/devel/run/copy-s3.rb +2 -0
  8. data/devel/run/email.rb +36 -0
  9. data/devel/run/email_imap.rb +43 -0
  10. data/devel/run/email_smime.rb +47 -0
  11. data/devel/run/init-icfs.rb +2 -0
  12. data/devel/run/webrick.rb +5 -57
  13. data/lib/icfs/api.rb +101 -90
  14. data/lib/icfs/cache.rb +2 -0
  15. data/lib/icfs/cache_elastic.rb +127 -125
  16. data/lib/icfs/{web/config.rb → config.rb} +3 -3
  17. data/lib/icfs/{web/config_redis.rb → config_redis.rb} +8 -8
  18. data/lib/icfs/{web/config_s3.rb → config_s3.rb} +8 -8
  19. data/lib/icfs/demo/auth.rb +5 -7
  20. data/lib/icfs/demo/static.rb +2 -0
  21. data/lib/icfs/elastic.rb +10 -8
  22. data/lib/icfs/email/basic.rb +242 -0
  23. data/lib/icfs/email/core.rb +293 -0
  24. data/lib/icfs/email/from.rb +52 -0
  25. data/lib/icfs/email/imap.rb +148 -0
  26. data/lib/icfs/email/smime.rb +139 -0
  27. data/lib/icfs/items.rb +5 -3
  28. data/lib/icfs/store.rb +20 -18
  29. data/lib/icfs/store_fs.rb +7 -5
  30. data/lib/icfs/store_s3.rb +4 -2
  31. data/lib/icfs/users.rb +5 -3
  32. data/lib/icfs/users_fs.rb +8 -6
  33. data/lib/icfs/users_redis.rb +12 -10
  34. data/lib/icfs/users_s3.rb +6 -4
  35. data/lib/icfs/utils/backup.rb +30 -29
  36. data/lib/icfs/utils/check.rb +36 -34
  37. data/lib/icfs/validate.rb +24 -15
  38. data/lib/icfs/web/auth_ssl.rb +7 -9
  39. data/lib/icfs/web/client.rb +671 -679
  40. data/lib/icfs.rb +174 -10
  41. metadata +16 -7
  42. data/devel/devel-webrick.yml +0 -49
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c6508e2169aa8ab7a2567c545e793c5f3af51a6b7d3426d7763ba148f1c2b71
4
- data.tar.gz: fc121b8053444a4757d7c9a1d1247a691baa8217aecf7963ba0ba1ffcc4ca358
3
+ metadata.gz: 28031e9c5c67e30c2cf4778fbf56a7840117d256e4384e6e044e7cc888958d09
4
+ data.tar.gz: 3abea632e084b00bd09ac570710eab52e99a152d073c6f96779a04c23dbc1c21
5
5
  SHA512:
6
- metadata.gz: bf90379adfeeb08e1cc1f8371eeb813d4259e187094b331f12d6232b6a10855044f0be14db531722b037b4a18c5c63be9830a13d24b443db4c98f1e62b8aaf25
7
- data.tar.gz: d307474f2ae62e6b5f1da6d9128bccc122088e8e0bee1ee3f50f6ad3895906ce9c9136c5f9df39d812c9ea0a85309ed5ac897398097523bf1edfb51f04f633d0
6
+ metadata.gz: cd28dc30f59e5bec1b272508d5b64ecb950a3e2b6d26d4318156069d19c338093177302ac09207a4b76b7decfa8272f84a8839f3165eeee28fdb9f15ae5c6ef3
7
+ data.tar.gz: '08f19a62a3d3c21cdf46c8120bd0b5846107a57409aba71939587affed4e7daf32c4d0bd805919d884baa4d24b520521527f62e8edf66ed6f886cf2237122b27'
@@ -10,6 +10,8 @@
10
10
  # This program is distributed WITHOUT ANY WARRANTY; without even the
11
11
  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
12
 
13
+ # frozen_string_literal: true
14
+
13
15
  require 'yaml'
14
16
  require 'faraday'
15
17
 
@@ -10,15 +10,23 @@
10
10
  # This program is distributed WITHOUT ANY WARRANTY; without even the
11
11
  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
12
 
13
+ # frozen_string_literal: true
14
+
13
15
  require 'openssl'
16
+ require 'yaml'
17
+
18
+ # read the configuration
19
+ cfg = YAML.load(File.read(ARGV[0]))
20
+
14
21
 
22
+ serial = Time.now.to_i
15
23
 
16
- # make a CA key
24
+ # make a CA cert
17
25
  ca_key = OpenSSL::PKey::RSA.new 2048
18
26
  ca_cert = OpenSSL::X509::Certificate.new
19
27
  ca_cert.version = 2
20
- ca_cert.serial = 1
21
- ca_cert.subject = OpenSSL::X509::Name.parse('/OU=org/OU=example/CN=Test Root CA')
28
+ ca_cert.serial = serial
29
+ ca_cert.subject = OpenSSL::X509::Name.parse(cfg['ca']['cn'])
22
30
  ca_cert.issuer = ca_cert.subject
23
31
  ca_cert.public_key = ca_key.public_key
24
32
  ca_cert.not_before = Time.now
@@ -36,11 +44,11 @@ ca_cert.sign(ca_key, OpenSSL::Digest::SHA256.new)
36
44
  File.open("ca_cert.pem", "wb"){|fi| fi.write ca_cert.to_pem }
37
45
 
38
46
 
39
- # make a server key
47
+ # make a server cert & key
40
48
  srv_key = OpenSSL::PKey::RSA.new 2048
41
49
  srv_cert = OpenSSL::X509::Certificate.new
42
50
  srv_cert.version = 2
43
- srv_cert.serial = 2
51
+ srv_cert.serial = serial + 1
44
52
  srv_cert.subject = OpenSSL::X509::Name.parse('/OU=org/OU=example/OU=Test Server/CN=localhost')
45
53
  srv_cert.issuer = ca_cert.subject
46
54
  srv_cert.public_key = srv_key.public_key
@@ -52,19 +60,22 @@ ef.issuer_certificate = ca_cert
52
60
  srv_cert.add_extension(ef.create_extension("basicConstraints", "CA:FALSE"))
53
61
  srv_cert.add_extension(ef.create_extension("keyUsage", "keyEncipherment,dataEncipherment,digitalSignature"))
54
62
  srv_cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
63
+ srv_cert.add_extension(ef.create_extension("subjectAltName", "email:%s" % cfg['server']['email'], false))
55
64
  srv_cert.sign(ca_key, OpenSSL::Digest::SHA256.new)
56
65
 
57
- # save server key
66
+ # save server cert & key
58
67
  File.open("srv_cert.pem", "wb"){|fi| fi.write srv_cert.to_pem }
59
68
  File.open("srv_key.pem", "wb"){|fi| fi.write srv_key.to_pem }
60
69
 
61
- # make client certs
62
- 5.times do |ix|
70
+ # make client certs with key included
71
+ cnt = 0
72
+ cfg['clients'].each do |cc|
73
+ cnt += 1
63
74
  clt_key = OpenSSL::PKey::RSA.new 2048
64
75
  clt_cert = OpenSSL::X509::Certificate.new
65
76
  clt_cert.version = 2
66
- clt_cert.serial = ix+3
67
- clt_cert.subject = OpenSSL::X509::Name.parse('/OU=org/OU=example/OU=Test Client/CN=client %d' % ix)
77
+ clt_cert.serial = serial + 2 + cnt
78
+ clt_cert.subject = OpenSSL::X509::Name.parse(cc['cn'])
68
79
  clt_cert.issuer = ca_cert.subject
69
80
  clt_cert.public_key = clt_key.public_key
70
81
  clt_cert.not_before = Time.now
@@ -74,11 +85,12 @@ File.open("srv_key.pem", "wb"){|fi| fi.write srv_key.to_pem }
74
85
  ef.issuer_certificate = ca_cert
75
86
  clt_cert.add_extension(ef.create_extension("basicConstraints", "CA:FALSE"))
76
87
  clt_cert.add_extension(ef.create_extension("keyUsage", "keyEncipherment,dataEncipherment,digitalSignature"))
88
+ clt_cert.add_extension(ef.create_extension("subjectAltName", "email:%s" % cc['email'], false))
77
89
  clt_cert.sign(ca_key, OpenSSL::Digest::SHA256.new)
78
90
 
79
91
  # pkcs12
80
- clt_pkcs12 = OpenSSL::PKCS12.create('demo', 'client-%d' % ix, clt_key, clt_cert)
92
+ clt_pkcs12 = OpenSSL::PKCS12.create('demo', 'client-%d' % cnt, clt_key, clt_cert)
81
93
 
82
- # save cert
83
- File.open('clt_%d.pfx' % ix, 'wb'){|fi| fi.write clt_pkcs12.to_der }
94
+ # save cert w/key
95
+ File.open('clt_%d.pfx' % cnt, 'wb'){|fi| fi.write clt_pkcs12.to_der }
84
96
  end
@@ -0,0 +1,14 @@
1
+
2
+ ca:
3
+ cn: "/OU=org/OU=example/CN=Test Root CA"
4
+
5
+ server:
6
+ cn: "/OU=org/OU=example/OU=Test Server/CN=localhost"
7
+ email: "server@example.org"
8
+
9
+ clients:
10
+ - cn: "/OU=org/OU=example/OU=Test Client/CN=client 1"
11
+ email: "client1@example.org"
12
+
13
+ - cn: "/OU=org/OU=example/OU=Test Client/CN=client 2"
14
+ email: "client2example.org"
@@ -16,7 +16,7 @@ RUN apk update && \
16
16
  apk upgrade && \
17
17
  apk --update add ruby fcgi ruby-json tzdata vim curl git bash && \
18
18
  apk --update add --virtual build-deps ruby-dev build-base fcgi-dev && \
19
- gem install -N rack webrick etc faraday yard aws-sdk-s3 redis && \
19
+ gem install -N rack webrick etc faraday yard aws-sdk-s3 redis mail && \
20
20
  apk del build-deps && \
21
21
  rm -rf /var/cache/apk/*
22
22
 
data/devel/run/base.rb ADDED
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Investigative Case File System
4
+ #
5
+ # Copyright 2019 by Graham A. Field
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License version 3.
9
+ #
10
+ # This program is distributed WITHOUT ANY WARRANTY; without even the
11
+ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+
13
+ # frozen_string_literal: true
14
+
15
+ require 'faraday'
16
+ require 'aws-sdk-s3'
17
+ require 'redis'
18
+
19
+ require_relative '../../lib/icfs'
20
+ require_relative '../../lib/icfs/cache_elastic'
21
+ require_relative '../../lib/icfs/store_s3'
22
+ require_relative '../../lib/icfs/users_s3'
23
+ require_relative '../../lib/icfs/users_redis'
24
+ require_relative '../../lib/icfs/config_s3'
25
+ require_relative '../../lib/icfs/config_redis'
26
+
27
+ #################################################
28
+ # Get the API
29
+ #
30
+ def get_base
31
+
32
+ # the log
33
+ log = Logger.new(STDERR)
34
+ log.level = Logger::INFO
35
+
36
+ # S3
37
+ s3 = Aws::S3::Client.new(
38
+ endpoint: 'http://minio:9000',
39
+ access_key_id: 'minio_key',
40
+ secret_access_key: 'minio_secret',
41
+ force_path_style: true,
42
+ region: 'us-east-1'
43
+ )
44
+
45
+ # redis
46
+ redis = Redis.new(host: 'redis')
47
+
48
+ # elasic
49
+ es = Faraday.new('http://elastic:9200')
50
+
51
+ # default mapping
52
+ map = {
53
+ entry: 'entry',
54
+ case: 'case',
55
+ action: 'action',
56
+ index: 'index',
57
+ log: 'log',
58
+ lock: 'lock',
59
+ current: 'current',
60
+ }.freeze
61
+
62
+ # default config
63
+ defaults = {
64
+ 'tz' => '-04:00'
65
+ }
66
+
67
+ # base objects
68
+ cache = ICFS::CacheElastic.new(map, es)
69
+ store = ICFS::StoreS3.new(s3, 'icfs', 'case/')
70
+ users_base = ICFS::UsersS3.new(s3, 'icfs', 'users/')
71
+ users = ICFS::UsersRedis.new(redis, users_base, {
72
+ prefix: 'users/',
73
+ expires: 60, # one minute cache for testing
74
+ log: log,
75
+ })
76
+ config_base = ICFS::ConfigS3.new(defaults, s3, 'icfs', 'config/')
77
+ config = ICFS::ConfigRedis.new(redis, config_base, {
78
+ prefix: 'config/',
79
+ expires: 60, # debug, only cache for one minute
80
+ })
81
+ api = ICFS::Api.new([], users, cache, store, config)
82
+
83
+ return {
84
+ cache: cache,
85
+ store: store,
86
+ users: users,
87
+ config: config,
88
+ api: api,
89
+ log: log,
90
+ }
91
+
92
+ end # def base
data/devel/run/copy-s3.rb CHANGED
@@ -10,6 +10,8 @@
10
10
  # This program is distributed WITHOUT ANY WARRANTY; without even the
11
11
  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
12
 
13
+ # frozen_string_literal: true
14
+
13
15
  require 'aws-sdk-s3'
14
16
  require 'find'
15
17
 
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Investigative Case File System
4
+ #
5
+ # Copyright 2019 by Graham A. Field
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License version 3.
9
+ #
10
+ # This program is distributed WITHOUT ANY WARRANTY; without even the
11
+ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+
13
+ # frozen_string_literal: true
14
+
15
+ require_relative 'base'
16
+ require_relative '../../lib/icfs/email/from'
17
+ require_relative '../../lib/icfs/email/basic'
18
+
19
+ # api
20
+ base = get_base
21
+ api = base[:api]
22
+ log = base[:log]
23
+ log.level = Logger::DEBUG
24
+
25
+ # load the email map
26
+ map_email = JSON.parse(File.read(ARGV[0]))
27
+
28
+ # email gateway
29
+ email_basic = ICFS::Email::Basic.new
30
+ email_from = ICFS::Email::From.new(map_email)
31
+ email = ICFS::Email::Core.new(api, log, [email_from, email_basic])
32
+
33
+ txt = STDIN.read
34
+ res = email.receive(txt)
35
+
36
+ p res
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Investigative Case File System
4
+ #
5
+ # Copyright 2019 by Graham A. Field
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License version 3.
9
+ #
10
+ # This program is distributed WITHOUT ANY WARRANTY; without even the
11
+ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+
13
+ # frozen_string_literal: true
14
+
15
+ # <app> <email_map.json> <config.json>
16
+
17
+ require_relative 'base'
18
+ require_relative '../../lib/icfs/email/from'
19
+ require_relative '../../lib/icfs/email/basic'
20
+ require_relative '../../lib/icfs/email/imap'
21
+
22
+ # api
23
+ base = get_base
24
+ api = base[:api]
25
+ log = base[:log]
26
+ log.level = Logger::DEBUG
27
+
28
+ # load the email map
29
+ map_email = JSON.parse(File.read(ARGV[0]))
30
+
31
+ # load the IMAP config
32
+ cfg_raw = JSON.parse(File.read(ARGV[1]))
33
+ cfg = {}
34
+ cfg_raw.each{|key, val| cfg[key.to_sym] = val}
35
+
36
+ # email gateway
37
+ email_basic = ICFS::Email::Basic.new
38
+ email_from = ICFS::Email::From.new(map_email)
39
+ email = ICFS::Email::Core.new(api, log, [email_from, email_basic])
40
+ imap = ICFS::Email::Imap.new(email, log, cfg)
41
+
42
+ # and fetch
43
+ imap.reconnect
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Investigative Case File System
4
+ #
5
+ # Copyright 2019 by Graham A. Field
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License version 3.
9
+ #
10
+ # This program is distributed WITHOUT ANY WARRANTY; without even the
11
+ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+
13
+ # <app> <srv_cert.pem> <srv_key.pem> <ca.pem> < <email.eml>
14
+
15
+ # frozen_string_literal: true
16
+
17
+ require_relative 'base'
18
+ require_relative '../../lib/icfs/email/smime'
19
+ require_relative '../../lib/icfs/email/basic'
20
+
21
+ # api
22
+ base = get_base
23
+ api = base[:api]
24
+ log = base[:log]
25
+ log.level = Logger::DEBUG
26
+
27
+ # load the email map
28
+ cert = ::OpenSSL::X509::Certificate.new(File.read(ARGV[0]))
29
+ key = ::OpenSSL::PKey.read(File.read(ARGV[1]))
30
+ ca = ::OpenSSL::X509::Store.new
31
+ ca.add_file(ARGV[2])
32
+
33
+ map_cn = {
34
+ 'CN=client 1,OU=Test Client,OU=example,OU=org' => 'user1',
35
+ 'CN=client 2,OU=Test Client,OU=example,OU=org' => 'user2',
36
+ 'CN=client 3,OU=Test Client,OU=example,OU=org' => 'user3',
37
+ }
38
+
39
+ # email gateway
40
+ email_basic = ICFS::Email::Basic.new
41
+ email_smime = ICFS::Email::Smime.new(key, cert, ca, map_cn)
42
+ email = ICFS::Email::Core.new(api, log, [email_smime, email_basic])
43
+
44
+ txt = STDIN.read
45
+ res = email.receive(txt)
46
+
47
+ p res
@@ -10,6 +10,8 @@
10
10
  # This program is distributed WITHOUT ANY WARRANTY; without even the
11
11
  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
12
 
13
+ # frozen_string_literal: true
14
+
13
15
  require 'json'
14
16
  require 'faraday'
15
17
  require 'aws-sdk-s3'
data/devel/run/webrick.rb CHANGED
@@ -10,68 +10,16 @@
10
10
  # This program is distributed WITHOUT ANY WARRANTY; without even the
11
11
  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
12
 
13
- require 'faraday'
14
- require 'aws-sdk-s3'
15
- require 'redis'
13
+ # frozen_string_literal: true
16
14
 
17
- require_relative '../../lib/icfs'
18
- require_relative '../../lib/icfs/cache_elastic'
19
- require_relative '../../lib/icfs/store_s3'
20
- require_relative '../../lib/icfs/users_s3'
21
- require_relative '../../lib/icfs/users_redis'
15
+ require_relative 'base'
22
16
  require_relative '../../lib/icfs/web/client'
23
- require_relative '../../lib/icfs/web/config_s3'
24
- require_relative '../../lib/icfs/web/config_redis'
25
17
  require_relative '../../lib/icfs/demo/auth'
26
18
  require_relative '../../lib/icfs/demo/static'
27
19
 
28
- # Minio config
29
- Aws.config.update(
30
- endpoint: 'http://minio:9000',
31
- access_key_id: 'minio_key',
32
- secret_access_key: 'minio_secret',
33
- force_path_style: true,
34
- region: 'us-east-1'
35
- )
20
+ base = get_base()
21
+ api = base[:api]
36
22
 
37
- # default mapping
38
- map = {
39
- entry: 'entry',
40
- case: 'case',
41
- action: 'action',
42
- index: 'index',
43
- log: 'log',
44
- lock: 'lock',
45
- current: 'current',
46
- }.freeze
47
-
48
- # default config
49
- defaults = {
50
- 'tz' => '-04:00'
51
- }
52
-
53
- # the log
54
- log = Logger.new(STDERR)
55
- log.level = Logger::INFO
56
-
57
- # base items
58
- s3 = Aws::S3::Client.new
59
- redis = Redis.new(host: 'redis')
60
- es = Faraday.new('http://elastic:9200')
61
- cache = ICFS::CacheElastic.new(map, es)
62
- store = ICFS::StoreS3.new(s3, 'icfs'.freeze, 'case/'.freeze)
63
- users_base = ICFS::UsersS3.new(s3, 'icfs'.freeze, 'users/'.freeze)
64
- users = ICFS::UsersRedis.new(redis, users_base, {
65
- prefix: 'users/'.freeze,
66
- expires: 60, # one minute cache for testing
67
- log: log,
68
- })
69
- api = ICFS::Api.new([], users, cache, store)
70
- config_base = ICFS::Web::ConfigS3.new(defaults, s3, 'icfs', 'config/')
71
- config = ICFS::Web::ConfigRedis.new(redis, config_base, {
72
- prefix: 'config/',
73
- expires: 60, # debug, only cache for one minute
74
- })
75
23
  web = ICFS::Web::Client.new('/static/icfs.css', '/static/icfs.js')
76
24
 
77
25
  # static files
@@ -87,7 +35,7 @@ static = {
87
35
  }
88
36
 
89
37
  app = Rack::Builder.new do
90
- use(ICFS::Demo::Auth, api, config)
38
+ use(ICFS::Demo::Auth, api)
91
39
  use(ICFS::Demo::Static, static)
92
40
  run web
93
41
  end