deputy53 0.6.4 → 0.13.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
  SHA1:
3
- metadata.gz: 217f1845177eea5e0ab32c345d91b417e371be0b
4
- data.tar.gz: 1a2e6eaf480af3717e8fa29cb6a2992fec35b775
3
+ metadata.gz: 3176f6abe3bb2ec36eec12b0e26d5aff702ac7d2
4
+ data.tar.gz: d0c2c6466d04300338952950d893d6dcbb7c908b
5
5
  SHA512:
6
- metadata.gz: 5d60478b9b1940f528d873cfe2b5b4c4a2783593e16ad7328407fc056d0b0ec1d7afd9fd6c663f07757a84252d0b229a24f479d2ff3b41fffbc7bfc86bf81af3
7
- data.tar.gz: 4d0e9fc2752d5ffcd6fd825976228aaac54126ee67148a96b44848bffa04f594f351b502945d6cf18f8c1e0a48236907a1f411a7ee13e8fe0618cd6b31abc171
6
+ metadata.gz: 3b204023a1ae60cd83a9c3813eb8d249f31ed6411ee67de290b6fbe696b6611317fc5a5d6811381345c70eba4dcbe25b18702c961f9fe3702f452e4011d98ca4
7
+ data.tar.gz: d436ea1be8d21f944e1a2e732b1cd66745795e7187fce93c0c2abd66ac943e205958d085001b0386ccc4eba0d248ddccf3e0677eb73f14f3fcd442ff57025d24
data/README.org CHANGED
@@ -26,10 +26,30 @@
26
26
 
27
27
  * Usage
28
28
 
29
+ ** Delegate a subdomain to a new hosted zone
30
+
29
31
  #+BEGIN_SRC shell
30
32
  deputy53 delegate <subdomain>
31
33
  #+END_SRC
32
34
 
35
+ ** Assign control of a subdomain to an IAM entity
36
+
37
+ If =identity= is omitted, it will be inferred from the subdomain.
38
+
39
+ #+BEGIN_SRC shell
40
+ deputy53 assign <subdomain> [identity]
41
+ #+END_SRC
42
+
43
+ ** Generate a policy granting control of this zone
44
+
45
+ If you need to review or modify the policy generated by ~deputy53~, the
46
+ =policy= command will dump it to =STDOUT= in a format suitable for use with
47
+ tools such as ~awscli~ or ~piranha~.
48
+
49
+ #+BEGIN_SRC shell
50
+ deputy53 policy <subdomain>
51
+ #+END_SRC
52
+
33
53
  * License
34
54
 
35
55
  ~deputy53~ is available under the [[https://tldrlegal.com/license/mit-license][MIT License]]. See ~LICENSE.txt~ for the full text.
data/UPGRADING.org ADDED
@@ -0,0 +1,6 @@
1
+ #+TITLE: Upgrading Notes
2
+
3
+ * 0.7 -> 0.8
4
+
5
+ - ~Deputy53::Route53#id~ now raises a ~ZoneNotFoundError~ when the requested
6
+ zone is not found, rather than a ~KeyError~.
@@ -0,0 +1,45 @@
1
+ require 'aws-sdk'
2
+ require 'json'
3
+ require_relative 'contracted_object'
4
+ require_relative 'iam'
5
+ require_relative 'route53'
6
+
7
+ module Deputy53
8
+ # Assigns control of a zone to an identity
9
+ class Assigner < ContractedObject
10
+ Contract None => IAM
11
+ def iam
12
+ @iam ||= IAM.new
13
+ end
14
+
15
+ Contract None => Route53
16
+ def route53
17
+ @route53 ||= Route53.new
18
+ end
19
+
20
+ Contract String => String
21
+ def policy(subdomain)
22
+ zone = route53.id(subdomain).sub(%r{^/}, '')
23
+ document = {
24
+ 'Version' => '2012-10-17',
25
+ 'Statement' => [
26
+ 'Effect' => 'Allow',
27
+ 'Action' => ['route53domains:*', 'route53:*'],
28
+ 'Resource' => "arn:aws:route53:::#{zone}"
29
+ ]
30
+ }
31
+ JSON.dump document
32
+ end
33
+
34
+ Contract String, String => Bool
35
+ def assign(subdomain, identity)
36
+ identity = iam.identity identity
37
+
38
+ true if iam.api.method("put_#{identity.type}_policy").call(
39
+ :"#{identity.type}_name" => identity.name,
40
+ policy_name: "manage-dns@#{subdomain}",
41
+ policy_document: policy(subdomain)
42
+ )
43
+ end
44
+ end
45
+ end
data/lib/deputy53/cli.rb CHANGED
@@ -1,9 +1,22 @@
1
1
  require_relative 'agent'
2
+ require_relative 'assigner'
2
3
 
3
4
  module Deputy53
5
+ # CommandLine Interface
4
6
  class CLI
5
7
  def delegate(subdomain)
6
8
  Agent.new(subdomain).delegate
7
9
  end
10
+
11
+ def assign(subdomain, user = nil)
12
+ subdomain = "#{subdomain}." unless subdomain.end_with? '.'
13
+ user ||= subdomain.split('.').slice(0..-3).join('.')
14
+ Assigner.new.assign(subdomain, user)
15
+ end
16
+
17
+ def policy(subdomain)
18
+ subdomain = "#{subdomain}." unless subdomain.end_with? '.'
19
+ Assigner.new.policy(subdomain)
20
+ end
8
21
  end
9
22
  end
@@ -0,0 +1,7 @@
1
+ module Deputy53
2
+ class NameError < ::NameError; end
3
+ class AmbiguousNameError < NameError; end
4
+ class NotFoundError < NameError; end
5
+ class ZoneNotFoundError < NotFoundError; end
6
+ class IdentityNotFoundError < NotFoundError; end
7
+ end
@@ -0,0 +1,68 @@
1
+ require 'aws-sdk'
2
+ require_relative 'contracted_object'
3
+ require_relative 'identity'
4
+ require_relative 'exceptions'
5
+
6
+ module Deputy53
7
+ # An IAM Client
8
+ class IAM < ContractedObject
9
+ Contract None => ::Aws::IAM::Client
10
+ def api
11
+ @api ||= ::Aws::IAM::Client.new region: region
12
+ end
13
+
14
+ Contract None => String
15
+ def region
16
+ ENV.fetch('AWS_DEFAULT_REGION') { 'us-west-2' }
17
+ end
18
+
19
+ Contract None => ArrayOf[::Aws::IAM::Types::User]
20
+ def users
21
+ @users ||= api.list_users.users
22
+ end
23
+
24
+ Contract None => ArrayOf[::Aws::IAM::Types::Group]
25
+ def groups
26
+ @groups ||= api.list_groups.groups
27
+ end
28
+ Contract None => ArrayOf[::Aws::IAM::Types::Role]
29
+ def roles
30
+ @roles ||= api.list_roles.roles
31
+ end
32
+
33
+ Contract None => ArrayOf[Identity]
34
+ def identities
35
+ @identities ||= [users, groups, roles]
36
+ .reduce(:+)
37
+ .map { |i| Identity.new i }
38
+ end
39
+
40
+ Contract None => ArrayOf[String]
41
+ def names
42
+ identities.map(&:name)
43
+ end
44
+
45
+ Contract String => Bool
46
+ def exists?(name)
47
+ names.include? name
48
+ end
49
+
50
+ Contract String => Bool
51
+ def unambiguous?(name)
52
+ names.count { |n| n == name } == 1
53
+ end
54
+
55
+ Contract String => Identity
56
+ def identity(name)
57
+ raise IdentityNotFoundError unless exists? name
58
+ raise AmbiguousNameError unless unambiguous? name
59
+
60
+ identities.select { |i| i.name == name }.first
61
+ end
62
+
63
+ Contract String => String
64
+ def id(name)
65
+ identity(name).id
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'contracted_object'
2
+
3
+ module Deputy53
4
+ # Unified class for Users, Groups, and Roles.
5
+ class Identity < ContractedObject
6
+ Contract Xor[::Aws::IAM::Types::User, ::Aws::IAM::Types::Group, ::Aws::IAM::Types::Role] => Identity
7
+ def initialize(identity)
8
+ @identity = identity
9
+ self
10
+ end
11
+
12
+ Contract None => Enum[:user, :group, :role]
13
+ def type
14
+ @type ||= @identity.arn.split(':').last.split('/').first.to_sym
15
+ end
16
+
17
+ Contract None => String
18
+ def name
19
+ @name ||= @identity.method("#{type}_name").call
20
+ end
21
+
22
+ Contract None => String
23
+ def id
24
+ @id ||= @identity.method("#{type}_id").call
25
+ end
26
+ end
27
+ end
@@ -1,4 +1,5 @@
1
1
  require 'aws-sdk'
2
+ require_relative 'exceptions'
2
3
 
3
4
  module Deputy53
4
5
  # A Route53 Client
@@ -35,7 +36,7 @@ module Deputy53
35
36
 
36
37
  Contract String => String
37
38
  def id(name)
38
- raise KeyError unless zone? name
39
+ raise ZoneNotFoundError unless zone? name
39
40
  zones(name).first.id
40
41
  end
41
42
  end
data/lib/deputy53.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require_relative 'deputy53/agent'
2
+ require_relative 'deputy53/assigner'
2
3
  require_relative 'deputy53/cli'
4
+ require_relative 'deputy53/exceptions'
3
5
  require_relative 'deputy53/contracted_object'
4
6
  require_relative 'deputy53/route53'
5
7
  require_relative 'deputy53/zone'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deputy53
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Olstrom
@@ -100,12 +100,17 @@ files:
100
100
  - Gemfile
101
101
  - LICENSE.txt
102
102
  - README.org
103
+ - UPGRADING.org
103
104
  - bin/deputy53
104
105
  - deputy53.gemspec
105
106
  - lib/deputy53.rb
106
107
  - lib/deputy53/agent.rb
108
+ - lib/deputy53/assigner.rb
107
109
  - lib/deputy53/cli.rb
108
110
  - lib/deputy53/contracted_object.rb
111
+ - lib/deputy53/exceptions.rb
112
+ - lib/deputy53/iam.rb
113
+ - lib/deputy53/identity.rb
109
114
  - lib/deputy53/route53.rb
110
115
  - lib/deputy53/zone.rb
111
116
  homepage: https://github.com/colstrom/deputy53