ccs 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddc7a13cb4e185260a511ead10fd9f75387fecdd42a4138d19e0a0de35cd9caf
4
- data.tar.gz: 8c99aa2c31cbd7a66bb1023f8b32872478691268b475b80f9bf6c203ebb978a1
3
+ metadata.gz: ce4380f6f1c426727a7147117ba50c7dc21866ec766ecf01083846e5340d8d79
4
+ data.tar.gz: 162d1b0bebdcbec23a1bb72b2c82d7ad4b6994c4ab6fc4258d1ebeebe29c61b9
5
5
  SHA512:
6
- metadata.gz: 6c8f8bff758c7917bee0a1f779f5a97594c863d19ae96a673b8ca630cfe0189649d326130c44b622799ce489b9486492c1bf9fb74ee38c6e998167f29a7cb8a5
7
- data.tar.gz: 0ac4cd8805f4addd47e7b224a7eff2a7fab360856294aed60444846946d9563c294d415bdbba9f72da3d7fe2f966b1cec18d5f51b97fc615e6a0da49d6da8d94
6
+ metadata.gz: 70e1cd7ac88384e75d62093429b4fa37a4b2aba6c6b3439e47c856653b2eac54c56b2e55d11281b2258ee0497a6e5008cc365b3f402ae3277e6612764af9e502
7
+ data.tar.gz: 8b580583449616952eedf65b13e7c893464cfb7fd3595ff2f238eaf933741211dad276df92d31008b54b7d0976ed727bc9a9471d109dc6d8697e3caa047e2f3c
@@ -0,0 +1,10 @@
1
+ ## 3.1.0 2020-11-23
2
+
3
+
4
+ ### Added
5
+
6
+ - `force` argument to overwrite remote documents when uploading (paweljw)
7
+ - YARD documentation (paweljw)
8
+
9
+
10
+ [Compare 3.0.0...3.1.0](https://github.com/occson/ccs/compare/3.0.0...3.1.0)
data/README.md CHANGED
@@ -6,9 +6,7 @@ Configuration control system
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
- ```ruby
10
- gem 'ccs'
11
- ```
9
+ gem 'ccs'
12
10
 
13
11
  And then execute:
14
12
 
@@ -27,6 +25,7 @@ Or install it yourself as:
27
25
  --access-token
28
26
  -p CCS_PASSPHRASE, CCS Passphrase
29
27
  --passphrase
28
+ -f, --[no-]force Overwrite remote documents when uploading
30
29
 
31
30
 
32
31
  ## Example
@@ -45,6 +44,10 @@ Upload local file
45
44
 
46
45
  ccs cp /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml
47
46
 
47
+ Upload local file, overwriting remote document if any'
48
+
49
+ ccs cp --force /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml
50
+
48
51
  Upload content from STDIN
49
52
 
50
53
  echo "{ a: 1 }" | ccs cp - ccs://workspace-name/0.1.0/path/to/file.yml
@@ -79,6 +82,13 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
79
82
 
80
83
  To install this gem onto your local machine, run `bin/rake install`. To release a new version, update the version number in `version.rb`, and then run `bin/rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
81
84
 
85
+ ## Documentation
86
+
87
+ Documentation for the code should be written in YARD format. It can be generated locally into the `doc` directory by running
88
+
89
+ bundle exec yard
90
+
91
+
82
92
  ## Contributing
83
93
 
84
94
  Bug reports and pull requests are welcome on GitHub at https://github.com/occson/ccs. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/exe/ccs CHANGED
@@ -42,6 +42,10 @@ when 'cp'
42
42
  options['passphrase'] = v
43
43
  end
44
44
 
45
+ option_parser.on('-f', '--[no-]force', 'Overwrite remote documents when uploading') do |v|
46
+ options['force'] = v
47
+ end
48
+
45
49
  option_parser.separator ''
46
50
  option_parser.separator 'Configure via environment variables:'
47
51
  option_parser.separator ' CCS_ACCESS_TOKEN'
@@ -57,6 +61,8 @@ when 'cp'
57
61
  option_parser.separator ' ccs cp ccs://workspace-name/0.1.0/path/to/file.yml /local/path/to/file.yml'
58
62
  option_parser.separator ' Upload local file'
59
63
  option_parser.separator ' ccs cp /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml'
64
+ option_parser.separator ' Upload local file, overwriting remote document if any'
65
+ option_parser.separator ' ccs cp --force /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml'
60
66
  option_parser.separator ' Upload content from STDIN'
61
67
  option_parser.separator ' echo "{ a: 1 }" | ccs cp - ccs://workspace-name/0.1.0/path/to/file.yml'
62
68
  option_parser.separator ' cat /local/path/to/file.yml | ccs cp - ccs://workspace-name/0.1.0/path/to/file.yml'
@@ -77,7 +83,7 @@ when 'cp'
77
83
  raise OptionParser::MissingArgument, 'source' unless arguments.fetch(0, nil)
78
84
  raise OptionParser::MissingArgument, 'destination' unless arguments.fetch(1, nil)
79
85
 
80
- exit(1) unless Ccs::Commands::Copy.new(arguments[0], arguments[1], options['access_token'], options['passphrase']).call
86
+ exit(1) unless Ccs::Commands::Copy.new(arguments[0], arguments[1], options['access_token'], options['passphrase'], force: options.fetch('force', false)).call
81
87
  else
82
88
  puts option_parser
83
89
  exit(1)
data/lib/ccs.rb CHANGED
@@ -12,6 +12,8 @@ require 'ccs/decrypter'
12
12
  require 'ccs/uploader'
13
13
  require 'ccs/downloader'
14
14
  require 'ccs/document'
15
+
15
16
  require 'ccs/commands/copy'
16
17
 
18
+ # Top level `Ccs` namespace.
17
19
  module Ccs; end
@@ -2,14 +2,37 @@
2
2
 
3
3
  module Ccs
4
4
  module Commands
5
+ # The copy command, responsible for copying a target to a destination, performing encryption
6
+ # and decryption as necessary.
7
+ #
8
+ # The target and destinations can be:
9
+ #
10
+ # - STDIN/STDOUT: a `-` sign is interpreted as these standard streams
11
+ #
12
+ # - The Occson server: strings beginning with `ccs://` or `http(s)://` are interpreted as such
13
+ #
14
+ # - local files: everything not matching the previous descriptions is assumed to
15
+ # be a path on the local system
5
16
  class Copy
6
- def initialize(source, destination, access_token, passphrase)
17
+ # Builds an instance of the Copy command.
18
+ #
19
+ # @param source [String] `-` for STDIN, an URI or a local file path
20
+ # @param destination [String] `-` for STDOUT, an URI or a local file path
21
+ # @param access_token [String] Occson access token
22
+ # @param passphrase [String] Passphrase used for encryption of the document
23
+ # @param force [Boolean] Whether to overwrite target document in Occson, if any. Default `false`.
24
+ def initialize(source, destination, access_token, passphrase, force: false)
7
25
  @source = source
8
26
  @destination = destination
9
27
  @access_token = access_token
10
28
  @passphrase = passphrase
29
+ @force = force
11
30
  end
12
31
 
32
+ # Performs a transfer between locations - an upload if `@source` is local or STDIN,
33
+ # a download if `@source` is an URI.
34
+ #
35
+ # No guarantees are made about the return values of this method.
13
36
  def call
14
37
  download? ? download : upload
15
38
  end
@@ -29,7 +52,7 @@ module Ccs
29
52
 
30
53
  def upload
31
54
  content = @source.eql?('-') ? STDIN.read : File.read(@source)
32
- Document.new(@destination, @access_token, @passphrase).upload(content)
55
+ Document.new(@destination, @access_token, @passphrase).upload(content, force: @force)
33
56
  end
34
57
  end
35
58
  end
@@ -1,12 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Handles client-side decryption for documents.
5
+ #
6
+ # The decrypter uses AES-256 in CBC mode internally. A salt is
7
+ # expected in bytes 8..15, with ciphertext occupying the
8
+ # further bytes.
4
9
  class Decrypter
10
+ # Constructs a Decrypter instance with given passphrase and content.
11
+ #
12
+ # @example
13
+ # Ccs::Decrypter.new('the content passphrase', content)
14
+ #
15
+ # @param passphrase [String] Passphrase for content decryption
16
+ # @param content [String] Encrypted document content
5
17
  def initialize(passphrase, content)
6
18
  @passphrase = passphrase
7
19
  @content = content
8
20
  end
9
21
 
22
+ # Performs decryption, returning plaintext if passphrase matched.
23
+ #
24
+ # @return [String] Plaintext document content
10
25
  def call
11
26
  decryptor.pkcs5_keyivgen(@passphrase, ciphertext_salt, 1)
12
27
  result = decryptor.update(encrypted)
@@ -1,17 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # An abstraction for the Document concept. Simplifies building URLs,
5
+ # uploading and downloading contents. Abstracts away workspaces due to
6
+ # the use of access tokens in constructions.
4
7
  class Document
8
+ # Constructs a Document instance from a given URI, access token and passphrase.
9
+ #
10
+ # @example
11
+ # uri = 'ccs://path/to/file.yml'
12
+ # access_token = 'f30b5450421362c9ca0b'
13
+ # passphrase = 'my document passphrase'
14
+ #
15
+ # Ccs::Document.new(uri, access_token, passphrase)
16
+ #
17
+ # @param uri [String] Document URI. Accepts `ccs://` as shorthand for Occson location.
18
+ # @param access_token [String] Occson access token.
19
+ # @param passphrase [String] Document passphrase, used in encryption and decryption.
5
20
  def initialize(uri, access_token, passphrase)
6
21
  @uri = build_uri(uri)
7
22
  @access_token = access_token
8
23
  @passphrase = passphrase
9
24
  end
10
25
 
11
- def upload(content)
12
- Uploader.new(@uri, content, @access_token, @passphrase).call
26
+ # Uploads the given plaintext `content` to target URI.
27
+ #
28
+ # @example
29
+ # document.upload('My example plaintext.')
30
+ #
31
+ # @param content [String] Plaintext to be encrypted and uploaded.
32
+ # @param force [Boolean] Whether to overwrite target document in Occson, if any. Default `false`.
33
+ def upload(content, force: false)
34
+ Uploader.new(@uri, content, @access_token, @passphrase, force: force).call
13
35
  end
14
36
 
37
+ # Downloads the encrypted document at `@uri` and returns the plaintext
38
+ # contents (given that `@passphrase` matches).
39
+ #
40
+ # @example
41
+ # plaintext = document.download
42
+ #
43
+ # @return [String] Decrypted document contents
15
44
  def download
16
45
  Downloader.new(@uri, @access_token, @passphrase).call
17
46
  end
@@ -1,13 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Downloads and decrypts the document at given URI with given access token.
5
+ # Decryption occurs using given passphrase.
4
6
  class Downloader
7
+ # Constructs a Downloader instance from a given URI, access token and passphrase.
8
+ #
9
+ # @example
10
+ # uri = 'ccs://path/to/file.yml'
11
+ # access_token = 'f30b5450421362c9ca0b'
12
+ # passphrase = 'my document passphrase'
13
+ #
14
+ # Ccs::Downloader.new(uri, access_token, passphrase)
15
+ #
16
+ # @param uri [String] Document URI. Accepts `ccs://` as shorthand for Occson location.
17
+ # @param access_token [String] Occson access token.
18
+ # @param passphrase [String] Document passphrase, used in encryption and decryption.
5
19
  def initialize(uri, access_token, passphrase)
6
20
  @uri = uri
7
21
  @access_token = access_token
8
22
  @passphrase = passphrase
9
23
  end
10
24
 
25
+ # Performs the download and decryption of document.
26
+ #
27
+ # @return [String|nil] Decrypted body of the document or `nil` in case the
28
+ # server did not respond with a `200` HTTP code.
11
29
  def call
12
30
  response = http.request(request)
13
31
  body = response.body
@@ -1,13 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Encrypts the given content for transmission. Uses AES-256 in CBC
5
+ # mode internally, with salting.
4
6
  class Encrypter
7
+ # Constructs an Encrypter instance with given passphrase, content and salt.
8
+ # Salt _must_ be exactly 8 characters long.
9
+ #
10
+ # @example
11
+ # passphrase = 'my long document passphrase'
12
+ # content = 'very secret content'
13
+ # salt = '12345678'
14
+ #
15
+ # Ccs::Encrypter.new(passphrase, content, salt)
16
+ #
17
+ # @param passphrase [String] Document passphrase.
18
+ # @param content [String] Plaintext content to be encrypted.
19
+ # @param salt [String] Salt to reinforce the encryption, included in
20
+ # plaintext in the encrypted document.
5
21
  def initialize(passphrase, content, salt)
6
22
  @passphrase = passphrase
7
23
  @content = content
8
24
  @salt = salt
9
25
  end
10
26
 
27
+ # Performs the actual encryption, returning base64-encoded ciphertext.
28
+ #
29
+ # @return [String] base64-encoded ciphertext
11
30
  def call
12
31
  encryptor.pkcs5_keyivgen(@passphrase, @salt, 1)
13
32
  encrypted = encryptor.update(@content)
@@ -1,17 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Encrypts and uploads the document to Occson.
4
5
  class Uploader
5
- def initialize(uri, content, access_token, passphrase)
6
+ # Constructs an Uploader instance from a given URI, content, access token and passphrase.
7
+ #
8
+ # @example
9
+ # uri = 'ccs://path/to/file.yml'
10
+ # content = 'my very secret message'
11
+ # access_token = 'f30b5450421362c9ca0b'
12
+ # passphrase = 'my document passphrase'
13
+ #
14
+ # Ccs::Uploader.new(uri, access_token, passphrase)
15
+ #
16
+ # @param uri [String] Document URI. Accepts `ccs://` as shorthand for Occson location.
17
+ # @param content [String] Plaintext for encryption and upload.
18
+ # @param access_token [String] Occson access token.
19
+ # @param passphrase [String] Document passphrase, used in encryption and decryption.
20
+ # @param force [Boolean] Whether to overwrite target document in Occson, if any. Default `false`.
21
+ def initialize(uri, content, access_token, passphrase, force: false)
6
22
  @uri = uri
7
23
  @content = content
8
24
  @access_token = access_token
9
25
  @passphrase = passphrase
26
+ @force = force.to_s
10
27
  end
11
28
 
29
+ # Performs the actual upload to server.
30
+ #
31
+ # @return [Boolean] `true` for a successful upload, `false` otherwise
12
32
  def call
13
- request.body = { encrypted_content: encrypted_content }.to_json
14
- http.request(request).code.eql? '201'
33
+ request.body = { encrypted_content: encrypted_content, force: @force }.to_json
34
+ %w[200 201].include?(http.request(request).code)
15
35
  end
16
36
 
17
37
  private
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
- VERSION = '3.0.0'
4
+ # Ccs gem version definition
5
+ VERSION = '3.1.0'
5
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ccs
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tkowalewski
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-10-23 00:00:00.000000000 Z
12
+ date: 2020-11-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: inch