cumulus-aws 0.11.1
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.
- checksums.yaml +15 -0
- data/.gitignore +3 -0
- data/.travis.yml +12 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +29 -0
- data/LICENSE +202 -0
- data/README.md +41 -0
- data/autocomplete +137 -0
- data/bin/cumulus +658 -0
- data/cumulus +2 -0
- data/cumulus-aws.gemspec +20 -0
- data/lib/autoscaling/AutoScaling.rb +40 -0
- data/lib/autoscaling/loader/Loader.rb +56 -0
- data/lib/autoscaling/manager/Manager.rb +360 -0
- data/lib/autoscaling/models/AlarmConfig.rb +165 -0
- data/lib/autoscaling/models/AlarmDiff.rb +172 -0
- data/lib/autoscaling/models/AutoScalingDiff.rb +178 -0
- data/lib/autoscaling/models/GroupConfig.rb +330 -0
- data/lib/autoscaling/models/PolicyConfig.rb +135 -0
- data/lib/autoscaling/models/PolicyDiff.rb +73 -0
- data/lib/autoscaling/models/ScheduledActionDiff.rb +53 -0
- data/lib/autoscaling/models/ScheduledConfig.rb +96 -0
- data/lib/aws_extensions/ec2/DhcpOptions.rb +41 -0
- data/lib/aws_extensions/ec2/Instance.rb +29 -0
- data/lib/aws_extensions/ec2/NetworkAcl.rb +25 -0
- data/lib/aws_extensions/ec2/NetworkInterface.rb +14 -0
- data/lib/aws_extensions/ec2/RouteTable.rb +26 -0
- data/lib/aws_extensions/ec2/SecurityGroup.rb +16 -0
- data/lib/aws_extensions/ec2/Subnet.rb +28 -0
- data/lib/aws_extensions/ec2/Volume.rb +24 -0
- data/lib/aws_extensions/ec2/Vpc.rb +14 -0
- data/lib/aws_extensions/ec2/VpcEndpoint.rb +11 -0
- data/lib/aws_extensions/elb/BackendServerDescription.rb +12 -0
- data/lib/aws_extensions/elb/PolicyDescription.rb +14 -0
- data/lib/aws_extensions/kinesis/StreamDescription.rb +12 -0
- data/lib/aws_extensions/route53/AliasTarget.rb +21 -0
- data/lib/aws_extensions/s3/Bucket.rb +33 -0
- data/lib/aws_extensions/s3/BucketAcl.rb +28 -0
- data/lib/aws_extensions/s3/BucketCors.rb +17 -0
- data/lib/aws_extensions/s3/BucketLifecycle.rb +21 -0
- data/lib/aws_extensions/s3/BucketLogging.rb +18 -0
- data/lib/aws_extensions/s3/BucketNotification.rb +23 -0
- data/lib/aws_extensions/s3/BucketPolicy.rb +18 -0
- data/lib/aws_extensions/s3/BucketTagging.rb +15 -0
- data/lib/aws_extensions/s3/BucketVersioning.rb +14 -0
- data/lib/aws_extensions/s3/BucketWebsite.rb +49 -0
- data/lib/aws_extensions/s3/CORSRule.rb +27 -0
- data/lib/aws_extensions/s3/ReplicationConfiguration.rb +22 -0
- data/lib/cloudfront/CloudFront.rb +83 -0
- data/lib/cloudfront/loader/Loader.rb +31 -0
- data/lib/cloudfront/manager/Manager.rb +183 -0
- data/lib/cloudfront/models/CacheBehaviorConfig.rb +237 -0
- data/lib/cloudfront/models/CacheBehaviorDiff.rb +211 -0
- data/lib/cloudfront/models/CustomOriginConfig.rb +51 -0
- data/lib/cloudfront/models/CustomOriginDiff.rb +74 -0
- data/lib/cloudfront/models/DistributionConfig.rb +183 -0
- data/lib/cloudfront/models/DistributionDiff.rb +131 -0
- data/lib/cloudfront/models/InvalidationConfig.rb +37 -0
- data/lib/cloudfront/models/OriginConfig.rb +144 -0
- data/lib/cloudfront/models/OriginDiff.rb +86 -0
- data/lib/cloudfront/models/OriginSslProtocols.rb +28 -0
- data/lib/cloudfront/models/OriginSslProtocolsDiff.rb +39 -0
- data/lib/common/BaseLoader.rb +80 -0
- data/lib/common/manager/Manager.rb +148 -0
- data/lib/common/models/Diff.rb +114 -0
- data/lib/common/models/ListChange.rb +21 -0
- data/lib/common/models/TagsDiff.rb +55 -0
- data/lib/common/models/UTCTimeSource.rb +17 -0
- data/lib/conf/Configuration.rb +365 -0
- data/lib/ec2/EC2.rb +503 -0
- data/lib/ec2/IPProtocolMapping.rb +165 -0
- data/lib/ec2/loaders/EbsLoader.rb +19 -0
- data/lib/ec2/loaders/InstanceLoader.rb +32 -0
- data/lib/ec2/managers/EbsManager.rb +176 -0
- data/lib/ec2/managers/InstanceManager.rb +509 -0
- data/lib/ec2/models/EbsGroupConfig.rb +133 -0
- data/lib/ec2/models/EbsGroupDiff.rb +48 -0
- data/lib/ec2/models/InstanceConfig.rb +202 -0
- data/lib/ec2/models/InstanceDiff.rb +95 -0
- data/lib/elb/ELB.rb +148 -0
- data/lib/elb/loader/Loader.rb +65 -0
- data/lib/elb/manager/Manager.rb +581 -0
- data/lib/elb/models/AccessLogConfig.rb +82 -0
- data/lib/elb/models/AccessLogDiff.rb +47 -0
- data/lib/elb/models/HealthCheckConfig.rb +91 -0
- data/lib/elb/models/HealthCheckDiff.rb +50 -0
- data/lib/elb/models/ListenerConfig.rb +99 -0
- data/lib/elb/models/ListenerDiff.rb +91 -0
- data/lib/elb/models/LoadBalancerConfig.rb +239 -0
- data/lib/elb/models/LoadBalancerDiff.rb +265 -0
- data/lib/iam/IAM.rb +36 -0
- data/lib/iam/loader/Loader.rb +117 -0
- data/lib/iam/manager/IamGroups.rb +98 -0
- data/lib/iam/manager/IamResource.rb +288 -0
- data/lib/iam/manager/IamRoles.rb +112 -0
- data/lib/iam/manager/IamUsers.rb +54 -0
- data/lib/iam/manager/Manager.rb +29 -0
- data/lib/iam/migration/AssumeRoleUnifier.rb +34 -0
- data/lib/iam/migration/PolicyUnifier.rb +90 -0
- data/lib/iam/models/GroupConfig.rb +40 -0
- data/lib/iam/models/IamDiff.rb +132 -0
- data/lib/iam/models/PolicyConfig.rb +67 -0
- data/lib/iam/models/ResourceWithPolicy.rb +208 -0
- data/lib/iam/models/RoleConfig.rb +53 -0
- data/lib/iam/models/StatementConfig.rb +35 -0
- data/lib/iam/models/UserConfig.rb +21 -0
- data/lib/kinesis/Kinesis.rb +94 -0
- data/lib/kinesis/loader/Loader.rb +19 -0
- data/lib/kinesis/manager/Manager.rb +206 -0
- data/lib/kinesis/models/StreamConfig.rb +75 -0
- data/lib/kinesis/models/StreamDiff.rb +58 -0
- data/lib/lambda/Lambda.rb +41 -0
- data/lib/route53/loader/Loader.rb +32 -0
- data/lib/route53/manager/Manager.rb +241 -0
- data/lib/route53/models/AliasTarget.rb +86 -0
- data/lib/route53/models/RecordConfig.rb +178 -0
- data/lib/route53/models/RecordDiff.rb +140 -0
- data/lib/route53/models/Vpc.rb +24 -0
- data/lib/route53/models/ZoneConfig.rb +156 -0
- data/lib/route53/models/ZoneDiff.rb +118 -0
- data/lib/s3/S3.rb +89 -0
- data/lib/s3/loader/Loader.rb +66 -0
- data/lib/s3/manager/Manager.rb +296 -0
- data/lib/s3/models/BucketConfig.rb +321 -0
- data/lib/s3/models/BucketDiff.rb +167 -0
- data/lib/s3/models/GrantConfig.rb +189 -0
- data/lib/s3/models/GrantDiff.rb +50 -0
- data/lib/s3/models/LifecycleConfig.rb +142 -0
- data/lib/s3/models/LifecycleDiff.rb +46 -0
- data/lib/s3/models/LoggingConfig.rb +81 -0
- data/lib/s3/models/NotificationConfig.rb +157 -0
- data/lib/s3/models/NotificationDiff.rb +62 -0
- data/lib/s3/models/ReplicationConfig.rb +133 -0
- data/lib/s3/models/ReplicationDiff.rb +60 -0
- data/lib/s3/models/WebsiteConfig.rb +107 -0
- data/lib/security/SecurityGroups.rb +39 -0
- data/lib/security/loader/Loader.rb +94 -0
- data/lib/security/manager/Manager.rb +246 -0
- data/lib/security/models/RuleConfig.rb +161 -0
- data/lib/security/models/RuleDiff.rb +72 -0
- data/lib/security/models/RuleMigration.rb +127 -0
- data/lib/security/models/SecurityGroupConfig.rb +172 -0
- data/lib/security/models/SecurityGroupDiff.rb +112 -0
- data/lib/sns/SNS.rb +40 -0
- data/lib/sqs/SQS.rb +62 -0
- data/lib/sqs/loader/Loader.rb +34 -0
- data/lib/sqs/manager/Manager.rb +128 -0
- data/lib/sqs/models/DeadLetterConfig.rb +70 -0
- data/lib/sqs/models/DeadLetterDiff.rb +35 -0
- data/lib/sqs/models/QueueConfig.rb +115 -0
- data/lib/sqs/models/QueueDiff.rb +89 -0
- data/lib/util/Colors.rb +111 -0
- data/lib/util/StatusCodes.rb +51 -0
- data/lib/vpc/loader/Loader.rb +73 -0
- data/lib/vpc/manager/Manager.rb +954 -0
- data/lib/vpc/models/AclEntryConfig.rb +150 -0
- data/lib/vpc/models/AclEntryDiff.rb +54 -0
- data/lib/vpc/models/DhcpConfig.rb +100 -0
- data/lib/vpc/models/DhcpDiff.rb +90 -0
- data/lib/vpc/models/EndpointConfig.rb +76 -0
- data/lib/vpc/models/EndpointDiff.rb +69 -0
- data/lib/vpc/models/NetworkAclConfig.rb +87 -0
- data/lib/vpc/models/NetworkAclDiff.rb +116 -0
- data/lib/vpc/models/RouteConfig.rb +82 -0
- data/lib/vpc/models/RouteDiff.rb +50 -0
- data/lib/vpc/models/RouteTableConfig.rb +92 -0
- data/lib/vpc/models/RouteTableDiff.rb +101 -0
- data/lib/vpc/models/SubnetConfig.rb +113 -0
- data/lib/vpc/models/SubnetDiff.rb +78 -0
- data/lib/vpc/models/VpcConfig.rb +173 -0
- data/lib/vpc/models/VpcDiff.rb +315 -0
- data/rakefile.rb +8 -0
- metadata +245 -0
data/lib/iam/IAM.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require "conf/Configuration"
|
|
2
|
+
|
|
3
|
+
require "aws-sdk"
|
|
4
|
+
|
|
5
|
+
module Cumulus
|
|
6
|
+
module IAM
|
|
7
|
+
class << self
|
|
8
|
+
@@client = Aws::IAM::Client.new(Configuration.instance.client)
|
|
9
|
+
|
|
10
|
+
# Public: Static method that will get the ARN of an IAM Role
|
|
11
|
+
#
|
|
12
|
+
# name - the name of the role to get
|
|
13
|
+
#
|
|
14
|
+
# Returns the String ARN or nil if there is no role
|
|
15
|
+
def get_role_arn(name)
|
|
16
|
+
@@client.get_role({
|
|
17
|
+
role_name: name
|
|
18
|
+
}).role.arn
|
|
19
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Public: Get the instance profile arn for a role
|
|
24
|
+
#
|
|
25
|
+
# name - the name of the role
|
|
26
|
+
def get_instance_profile_arn(name)
|
|
27
|
+
@@client.get_instance_profile({
|
|
28
|
+
instance_profile_name: name
|
|
29
|
+
}).instance_profile.arn
|
|
30
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
require "conf/Configuration"
|
|
2
|
+
require "iam/models/GroupConfig"
|
|
3
|
+
require "iam/models/StatementConfig"
|
|
4
|
+
require "iam/models/RoleConfig"
|
|
5
|
+
require "iam/models/UserConfig"
|
|
6
|
+
require "common/BaseLoader"
|
|
7
|
+
|
|
8
|
+
require "json"
|
|
9
|
+
|
|
10
|
+
module Cumulus
|
|
11
|
+
module IAM
|
|
12
|
+
# Public: A module that handles loading all the json configuration files and
|
|
13
|
+
# creating objects from them.
|
|
14
|
+
module Loader
|
|
15
|
+
include Common::BaseLoader
|
|
16
|
+
|
|
17
|
+
@@group_loader = Proc.new { |name, json| GroupConfig.new(name, json) }
|
|
18
|
+
@@groups_dir = Configuration.instance.iam.groups_directory
|
|
19
|
+
@@role_loader = Proc.new { |name, json| RoleConfig.new(name, json) }
|
|
20
|
+
@@roles_dir = Configuration.instance.iam.roles_directory
|
|
21
|
+
@@user_loader = Proc.new { |name, json| UserConfig.new(name, json) }
|
|
22
|
+
@@users_dir = Configuration.instance.iam.users_directory
|
|
23
|
+
@@static_policy_dir = Configuration.instance.iam.static_policy_directory
|
|
24
|
+
@@template_dir = Configuration.instance.iam.template_policy_directory
|
|
25
|
+
@@policy_loader = Proc.new do |name, json|
|
|
26
|
+
if json.is_a?(Array)
|
|
27
|
+
json.map do |s|
|
|
28
|
+
StatementConfig.new(s)
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
StatementConfig.new(json)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Public: Load all the roles defined in configuration.
|
|
36
|
+
#
|
|
37
|
+
# Returns an Array of RoleConfig objects defined by the roles configuration
|
|
38
|
+
# files.
|
|
39
|
+
def Loader.roles
|
|
40
|
+
Common::BaseLoader.resources(@@roles_dir, &@@role_loader)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Public: Load a role defined in configuration
|
|
44
|
+
#
|
|
45
|
+
# file - the name of the role to load
|
|
46
|
+
#
|
|
47
|
+
# Returns a RoleConfig object defined by the role configuration files.
|
|
48
|
+
def Loader.role(file)
|
|
49
|
+
Common::BaseLoader.resource(file, @@roles_dir, &@@role_loader)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Public: Load all the users defined in configuration.
|
|
53
|
+
#
|
|
54
|
+
# Returns an Array of UserConfig objects defined in user configuration files.
|
|
55
|
+
def Loader.users
|
|
56
|
+
Common::BaseLoader.resources(@@users_dir, &@@user_loader)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Public: Load a user defined in configuration
|
|
60
|
+
#
|
|
61
|
+
# file - the file the user definition is found in
|
|
62
|
+
#
|
|
63
|
+
# Returns the UserConfig object defined by the file.
|
|
64
|
+
def Loader.user(file)
|
|
65
|
+
Common::BaseLoader.resource(file, @@users_dir, &@@user_loader)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Public: Load all the groups defined in configuration.
|
|
69
|
+
#
|
|
70
|
+
# Returns an Array of GroupConfig objects defined by the groups configuration
|
|
71
|
+
# files.
|
|
72
|
+
def Loader.groups
|
|
73
|
+
Common::BaseLoader.resources(@@groups_dir, &@@group_loader)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Public: Load a group defined in configuration
|
|
77
|
+
#
|
|
78
|
+
# file - the file the group definition is found in
|
|
79
|
+
#
|
|
80
|
+
# Returns the GroupConfig object defined by the file
|
|
81
|
+
def Loader.group(file)
|
|
82
|
+
Common::BaseLoader.resource(file, @@groups_dir, &@@group_loader)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Public: Load in a static policy as StatementConfig object
|
|
86
|
+
#
|
|
87
|
+
# file - the String name of the static policy file to load
|
|
88
|
+
#
|
|
89
|
+
# Returns a StatementConfig object corresponding to the static policy
|
|
90
|
+
def Loader.static_policy(file)
|
|
91
|
+
Common::BaseLoader.resource(file, @@static_policy_dir, &@@policy_loader)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Public: Load in a template policy, apply variables, and create a
|
|
95
|
+
# StatementConfig object from the result
|
|
96
|
+
#
|
|
97
|
+
# file - the String name of the template policy file to load
|
|
98
|
+
# variables - a Hash of variables to apply to the template
|
|
99
|
+
#
|
|
100
|
+
# Returns a StatementConfig object corresponding to the applied template policy
|
|
101
|
+
def Loader.template_policy(file, variables)
|
|
102
|
+
Common::BaseLoader.template(file, @@template_dir, variables, &@@policy_loader)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Public: Load the JSON string that is a role's policy document from a file.
|
|
106
|
+
#
|
|
107
|
+
# file - the String name of the policy document file to load
|
|
108
|
+
#
|
|
109
|
+
# Returns the String contents of the policy document file
|
|
110
|
+
def Loader.policy_document(file)
|
|
111
|
+
policy_dir = Configuration.instance.iam.policy_document_directory
|
|
112
|
+
Common::BaseLoader.load_file(file, policy_dir)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require "common/models/Diff"
|
|
2
|
+
require "iam/loader/Loader"
|
|
3
|
+
require "iam/models/IamDiff"
|
|
4
|
+
require "iam/manager/IamResource"
|
|
5
|
+
require "iam/models/GroupConfig"
|
|
6
|
+
require "util/Colors"
|
|
7
|
+
|
|
8
|
+
require "aws-sdk"
|
|
9
|
+
|
|
10
|
+
module Cumulus
|
|
11
|
+
module IAM
|
|
12
|
+
# Public: Manager class for IAM Groups
|
|
13
|
+
class IamGroups < IamResource
|
|
14
|
+
|
|
15
|
+
def initialize(iam)
|
|
16
|
+
super(iam)
|
|
17
|
+
@type = "group"
|
|
18
|
+
@migration_dir = "groups"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def local_resources
|
|
22
|
+
local = {}
|
|
23
|
+
Loader.groups.each do |group|
|
|
24
|
+
local[group.name] = group
|
|
25
|
+
end
|
|
26
|
+
local
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def one_local(name)
|
|
30
|
+
Loader.group(name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def aws_resources
|
|
34
|
+
@aws_groups ||= init_aws_groups
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def init_aws_groups
|
|
38
|
+
@iam.list_groups().groups.map do |group|
|
|
39
|
+
Aws::IAM::Group.new(group.group_name, { :client => @iam })
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def create(difference)
|
|
44
|
+
@iam.create_group({
|
|
45
|
+
:group_name => difference.local.name
|
|
46
|
+
})
|
|
47
|
+
resource = Aws::IAM::Group.new(difference.local.name, { :client => @iam })
|
|
48
|
+
add_users(resource, difference.local.users)
|
|
49
|
+
resource
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def update(resource, diffs)
|
|
53
|
+
super(resource, diffs)
|
|
54
|
+
|
|
55
|
+
if diffs.size == 1 and diffs[0].type == Common::DiffChange::ADD
|
|
56
|
+
puts Colors.blue("\tadding users...")
|
|
57
|
+
add_users(resource, diffs[0].local.users)
|
|
58
|
+
else
|
|
59
|
+
diffs.each do |diff|
|
|
60
|
+
if diff.type == IamChange::USER
|
|
61
|
+
puts Colors.blue("\tupdating users...")
|
|
62
|
+
add_users(resource, diff.added_users)
|
|
63
|
+
diff.removed_users.each { |u| resource.remove_user({ :user_name => u }) }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def empty_config
|
|
70
|
+
GroupConfig.new
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def migrate_additional(configs_to_aws)
|
|
74
|
+
configs_to_aws.map do |config, resource|
|
|
75
|
+
config.users = resource.users.map { |u| u.name }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
# Internal: Add the users assigned to the group to the group, handling the
|
|
82
|
+
# case that the user doesn't exist
|
|
83
|
+
#
|
|
84
|
+
# resource - the aws group resource
|
|
85
|
+
# users - the users to add
|
|
86
|
+
def add_users(resource, users)
|
|
87
|
+
users.each do |u|
|
|
88
|
+
begin
|
|
89
|
+
resource.add_user({ :user_name => u })
|
|
90
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
91
|
+
puts Colors.red("\tNo such user #{u}!")
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
require "common/models/Diff"
|
|
2
|
+
require "iam/migration/PolicyUnifier"
|
|
3
|
+
require "iam/models/IamDiff"
|
|
4
|
+
require "util/Colors"
|
|
5
|
+
require "util/StatusCodes"
|
|
6
|
+
|
|
7
|
+
require 'uri'
|
|
8
|
+
|
|
9
|
+
module Cumulus
|
|
10
|
+
module IAM
|
|
11
|
+
# Internal: Represents the manager of a type of IamResource. Base class for
|
|
12
|
+
# groups, roles, and users.
|
|
13
|
+
class IamResource
|
|
14
|
+
@@diff = Proc.new do |name, diffs|
|
|
15
|
+
if diffs.size > 0
|
|
16
|
+
|
|
17
|
+
if diffs.reject(&:info_only).size > 0
|
|
18
|
+
StatusCodes::set_status(StatusCodes::DIFFS)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if diffs.size == 1 and (diffs[0].type == Common::DiffChange::ADD or
|
|
22
|
+
diffs[0].type == Common::DiffChange::UNMANAGED)
|
|
23
|
+
puts diffs[0]
|
|
24
|
+
else
|
|
25
|
+
puts "#{name} has the following changes:"
|
|
26
|
+
diffs.each do |diff|
|
|
27
|
+
diff_string = diff.to_s.lines.map { |s| "\t#{s}" }.join
|
|
28
|
+
puts diff_string
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# =====================================================
|
|
35
|
+
# Methods to be overridden
|
|
36
|
+
# =====================================================
|
|
37
|
+
# Public: Get the local resources
|
|
38
|
+
#
|
|
39
|
+
# Returns an array of resources
|
|
40
|
+
def local_resources
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Public: Get one local resource
|
|
45
|
+
#
|
|
46
|
+
# name - the name of the resource to load
|
|
47
|
+
#
|
|
48
|
+
# Returns one local resource
|
|
49
|
+
def one_local(name)
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Public: Get resources from AWS
|
|
54
|
+
#
|
|
55
|
+
# Returns an array of resources from AWS
|
|
56
|
+
def aws_resources
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Public: Create a resource in AWS
|
|
61
|
+
#
|
|
62
|
+
# difference - the Diff object that contains the local differences
|
|
63
|
+
#
|
|
64
|
+
# Returns the created resource
|
|
65
|
+
def create(difference)
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Public: Create an empty config object
|
|
70
|
+
#
|
|
71
|
+
# Returns the created config object
|
|
72
|
+
def empty_config
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Public: When migrating, provide a config with any resource type specific
|
|
77
|
+
# data.
|
|
78
|
+
#
|
|
79
|
+
# configs_to_aws - an array of arrays where each inner array's first element
|
|
80
|
+
# is the configuration generated so far, and the second
|
|
81
|
+
# element is the corresponding aws resource
|
|
82
|
+
def migrate_additional(configs_to_aws)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# =====================================================
|
|
86
|
+
# End methods to be overridden
|
|
87
|
+
# =====================================================
|
|
88
|
+
|
|
89
|
+
# Public: Constructor
|
|
90
|
+
#
|
|
91
|
+
# iam - the IAM client to use
|
|
92
|
+
def initialize(iam)
|
|
93
|
+
@iam = iam
|
|
94
|
+
@migration_root = "generated"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Public: Print out the diff between the local configuration and the IAMS
|
|
98
|
+
# in AWS
|
|
99
|
+
def diff
|
|
100
|
+
each_difference(local_resources, true, &@@diff)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Public: Print out the diff between local configuration and AWS for one
|
|
104
|
+
# resource
|
|
105
|
+
#
|
|
106
|
+
# name - the name of the resource to diff
|
|
107
|
+
def diff_one(name)
|
|
108
|
+
each_difference({ name => one_local(name) }, false, &@@diff)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Public: Print out a list of resources defined by local configuration.
|
|
112
|
+
def list
|
|
113
|
+
puts local_resources.map { |name, resource| name }.join(" ")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Public: Sync the local configuration with the configuration in AWS. Will
|
|
117
|
+
# not delete resources that are not locally configured; also will not remove
|
|
118
|
+
# inline policies that are not locally configured.
|
|
119
|
+
def sync
|
|
120
|
+
each_difference(local_resources, true) { |name, diffs| sync_difference(name, diffs) }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Public: Sync the local configuration for one resource with AWS
|
|
124
|
+
#
|
|
125
|
+
# name - the name of the resource to sync
|
|
126
|
+
def sync_one(name)
|
|
127
|
+
each_difference({ name => one_local(name) }, false) { |name, diffs| sync_difference(name, diffs) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Public: Migrate AWS IAMs to Cumulus configuration.
|
|
131
|
+
def migrate
|
|
132
|
+
assets = "#{@migration_root}/#{@migration_dir}"
|
|
133
|
+
policies_dir = "#{@migration_root}/policies"
|
|
134
|
+
statics_dir = "#{policies_dir}/static"
|
|
135
|
+
|
|
136
|
+
if !Dir.exists?(@migration_root)
|
|
137
|
+
Dir.mkdir(@migration_root)
|
|
138
|
+
end
|
|
139
|
+
if !Dir.exists?(assets)
|
|
140
|
+
Dir.mkdir(assets)
|
|
141
|
+
end
|
|
142
|
+
if !Dir.exists?(policies_dir)
|
|
143
|
+
Dir.mkdir(policies_dir)
|
|
144
|
+
end
|
|
145
|
+
if !Dir.exists?(statics_dir)
|
|
146
|
+
Dir.mkdir(statics_dir)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# generate the configuration objects. This MUST be done separate from
|
|
150
|
+
# writing to file, because the unifier will change the configuration objects
|
|
151
|
+
# as it finds ways to unify configured attributes.
|
|
152
|
+
policy_unifier = PolicyUnifier.new(statics_dir)
|
|
153
|
+
configs = aws_resources.map do |resource|
|
|
154
|
+
puts "Processing #{@type} #{resource.name}..."
|
|
155
|
+
config = empty_config
|
|
156
|
+
config.name = resource.name
|
|
157
|
+
|
|
158
|
+
config.attached_policies = resource.attached_policies.map { |p| p.arn }
|
|
159
|
+
|
|
160
|
+
resource.policies.each do |policy|
|
|
161
|
+
statements = JSON.parse(URI.decode(policy.policy_document))["Statement"]
|
|
162
|
+
statements.each { |statement| statement.delete("Sid") }
|
|
163
|
+
policy_unifier.unify(config, statements, policy.name)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
[config, resource]
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
migrate_additional(configs)
|
|
170
|
+
configs = configs.map { |config, resource| config }
|
|
171
|
+
|
|
172
|
+
# write the configuration to file
|
|
173
|
+
puts "Writing configuration to file..."
|
|
174
|
+
configs.each do |config|
|
|
175
|
+
File.open("#{assets}/#{config.name}.json", 'w') { |f| f.write(config.json) }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
puts "Done."
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Public: Update a resource in AWS
|
|
182
|
+
#
|
|
183
|
+
# resource - the resource to update
|
|
184
|
+
# diffs - the diff objects to be used when updating the resource
|
|
185
|
+
def update(resource, diffs)
|
|
186
|
+
if diffs.size == 1 and diffs[0].type == Common::DiffChange::ADD
|
|
187
|
+
if !diffs[0].local.policy.empty?
|
|
188
|
+
update_policy(resource, diffs[0].local.generated_policy_name, diffs[0].local.policy)
|
|
189
|
+
end
|
|
190
|
+
if !diffs[0].local.attached_policies.empty?
|
|
191
|
+
update_attached(resource, diffs[0].local.attached_policies, [])
|
|
192
|
+
end
|
|
193
|
+
else
|
|
194
|
+
diffs.each do |diff|
|
|
195
|
+
case diff.type
|
|
196
|
+
when IamChange::POLICY
|
|
197
|
+
update_policy(resource, diff.policy_name, diff.local)
|
|
198
|
+
when IamChange::ATTACHED
|
|
199
|
+
update_attached(resource, diff.attached, diff.detached)
|
|
200
|
+
when IamChange::ADDED_POLICY
|
|
201
|
+
update_policy(resource, diff.policy_name, diff.local)
|
|
202
|
+
when IamChange::UNMANAGED_POLICY
|
|
203
|
+
puts Colors.unmanaged("\t#{diff.policy_name} is not managed by Cumulus")
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
|
|
211
|
+
# Internal: Loop through the differences between local configuration and AWS
|
|
212
|
+
#
|
|
213
|
+
# locals - the local configurations to compare against
|
|
214
|
+
# include_unmanaged - whether to include unmanaged resources in the list of
|
|
215
|
+
# changes
|
|
216
|
+
# f - will be passed the name of the resource and an array of
|
|
217
|
+
# IamDiffs
|
|
218
|
+
def each_difference(locals, include_unmanaged, &f)
|
|
219
|
+
aws = Hash[aws_resources.map { |aws| [aws.name, aws] }]
|
|
220
|
+
|
|
221
|
+
if include_unmanaged
|
|
222
|
+
aws.each do |name, resource|
|
|
223
|
+
f.call(name, [IamDiff.unmanaged(resource)]) if !locals.include?(name)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
locals.each do |name, resource|
|
|
227
|
+
if !aws.include?(name)
|
|
228
|
+
f.call(name, [IamDiff.added(resource)])
|
|
229
|
+
else
|
|
230
|
+
f.call(name, resource.diff(aws[name]))
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Internal: Sync differences
|
|
236
|
+
#
|
|
237
|
+
# name - the name of the resource to sync
|
|
238
|
+
# diffs - the differences between the configuration and AWS
|
|
239
|
+
def sync_difference(name, diffs)
|
|
240
|
+
aws = Hash[aws_resources.map { |aws| [aws.name, aws] }]
|
|
241
|
+
if diffs.size > 0
|
|
242
|
+
StatusCodes::set_status(StatusCodes::SYNC_DIFFS)
|
|
243
|
+
|
|
244
|
+
if diffs[0].type == Common::DiffChange::UNMANAGED
|
|
245
|
+
puts diffs[0]
|
|
246
|
+
elsif diffs[0].type == Common::DiffChange::ADD
|
|
247
|
+
puts Colors.added("creating #{name}...")
|
|
248
|
+
resource = create(diffs[0])
|
|
249
|
+
update(resource, diffs)
|
|
250
|
+
else
|
|
251
|
+
puts Colors.blue("updating #{name}...")
|
|
252
|
+
resource = aws[name]
|
|
253
|
+
update(resource, diffs)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Internal: Update the generated policy
|
|
259
|
+
#
|
|
260
|
+
# resource - the AWS resource to update
|
|
261
|
+
# name - the name of the policy to update
|
|
262
|
+
# config - the policy config to use when updating
|
|
263
|
+
def update_policy(resource, name, config)
|
|
264
|
+
puts Colors.blue("\tupdating policy #{name}...")
|
|
265
|
+
policy = resource.policy(name)
|
|
266
|
+
if config.empty?
|
|
267
|
+
policy.delete()
|
|
268
|
+
else
|
|
269
|
+
policy.put({
|
|
270
|
+
:policy_document => config.as_pretty_json
|
|
271
|
+
})
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Internal: Update the attached policies
|
|
276
|
+
#
|
|
277
|
+
# resource - the AWS resource to update
|
|
278
|
+
# attach - the policy arns to attach
|
|
279
|
+
# detach - the policy arns to detach
|
|
280
|
+
def update_attached(resource, attach, detach)
|
|
281
|
+
puts Colors.blue("\tupdating attached policies...")
|
|
282
|
+
attach.each { |arn| resource.attach_policy({ :policy_arn => arn }) }
|
|
283
|
+
detach.each { |arn| resource.detach_policy({ :policy_arn => arn }) }
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|