Skip to content

Commit a47d1cf

Browse files
author
Nick Hawkins
committed
Working on issue awslabs#14 - support for building roles with direct federation
1 parent 112836f commit a47d1cf

File tree

3 files changed

+91
-20
lines changed

3 files changed

+91
-20
lines changed

bin/iam_template_build.py

+29-6
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def policy_document_from_jinja(c, policy_name, model):
8282
return(template_json)
8383

8484

85-
def build_role_trust(c, trusts):
85+
def build_role_trust(c, trusts, SamlDirect=False):
8686
policy = {
8787
"Version": "2012-10-17",
8888
"Statement": [],
@@ -124,14 +124,23 @@ def build_role_trust(c, trusts):
124124
aws_principals.append(
125125
GetAtt(scrub_name("{}Role".format(trust)), "Arn")
126126
)
127-
# Next see if we match our SAML trust.
127+
# Next see if we match our SAML trust if saml_direct: False
128128
elif trust == c.saml_provider:
129129
saml_principals.append(
130130
"arn:aws:iam::"
131131
+ c.parent_account_id
132132
+ ":saml-provider/"
133133
+ c.saml_provider
134134
)
135+
# Check if this is a SAML Direct config (if saml_direct: True)
136+
elif SamlDirect:
137+
saml_principals.append(
138+
"arn:aws:iam::"
139+
+ c.current_account_id
140+
+ ":saml-provider/"
141+
+ trust
142+
)
143+
135144
# See if we match a user or role ARN Principal
136145
elif re.match("arn:aws:iam::\d{12}:(user|role)/.*?", trust) or \
137146
re.match("arn:aws:sts::\d{12}:assumed-role/.*?/.*?", trust):
@@ -360,11 +369,11 @@ def create_instance_profile(c, RoleName, model, named=False):
360369
])
361370

362371

363-
def add_role(c, RoleName, model, named=False):
372+
def add_role(c, RoleName, model, named=False, SamlDirect=False ):
364373
cfn_name = scrub_name(RoleName + "Role")
365374
kw_args = {
366375
"Path": "/",
367-
"AssumeRolePolicyDocument": build_role_trust(c, model['trusts']),
376+
"AssumeRolePolicyDocument": build_role_trust(c, model['trusts'], SamlDirect),
368377
"ManagedPolicyArns": [],
369378
"Policies": []
370379
}
@@ -499,7 +508,8 @@ def add_user(c, UserName, model, named=False):
499508
"users": True,
500509
"groups": True
501510
},
502-
"template_outputs": "enabled"
511+
"template_outputs": "enabled",
512+
"saml_direct": False
503513
}
504514

505515
# Policies
@@ -540,19 +550,32 @@ def add_user(c, UserName, model, named=False):
540550
)
541551

542552
# Roles
553+
554+
555+
543556
if "roles" in c.config:
557+
# first check if this is a saml_direct config - we do it this way instead of c.config["global"]["saml_direct"] so that existing configs (pre saml_direct support) will work without error
558+
saml_direct = False
559+
try:
560+
if c.config['global']['saml_direct'] is True:
561+
saml_direct = True
562+
except Exception:
563+
pass
564+
544565
for role_name in c.config["roles"]:
545566
context = ["all"]
546567
if "in_accounts" in c.config["roles"][role_name]:
547568
context = c.config["roles"][role_name]["in_accounts"]
548569

549570
for account in c.search_accounts(context):
550571
c.current_account = account
572+
c.current_account_id = str(c.config['accounts'][account]['id'])
551573
add_role(
552574
c,
553575
role_name,
554576
c.config["roles"][role_name],
555-
c.config["global"]["names"]["roles"]
577+
c.config["global"]["names"]["roles"],
578+
saml_direct
556579
)
557580

558581
# See if we need to add an instance profile too with an ec2 trust.

bin/lib/config_helper.py

+23-14
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,15 @@ def __init__(self, config_file):
3737
self.account_map_names = {}
3838
# Our parent account.
3939
self.parent = ""
40-
# SAML Provider
40+
# SAML Provider for hub-spoke
4141
self.saml_provider = ""
42+
# Determine if this is a hub-spoke SAML config or a SAML Direct config
43+
saml_hub_spoke = True
44+
try:
45+
if self.config['global']['saml_direct'] is True:
46+
saml_hub_spoke = False
47+
except Exception:
48+
pass
4249
for account in self.config['accounts']:
4350
account_id = str(self.config['accounts'][account]['id'])
4451
# Append to our array of account IDS:
@@ -63,19 +70,21 @@ def __init__(self, config_file):
6370
Export=Export(Sub("${AWS::StackName}-" + "TemplateBuild"))
6471
)
6572
])
66-
if "parent" in self.config['accounts'][account]:
67-
if self.config['accounts'][account]['parent'] is True:
68-
self.parent_account = account
69-
self.parent_account_id = account_id
70-
if "saml_provider" in self.config['accounts'][account]:
71-
self.saml_provider = \
72-
self.config['accounts'][account]["saml_provider"]
73-
if self.parent_account == "":
74-
raise Exception(
75-
"No account is marked as parent in the configuration file. "
76-
"One account should have parent: true"
77-
)
78-
73+
if saml_hub_spoke is True:
74+
if "parent" in self.config['accounts'][account]:
75+
if self.config['accounts'][account]['parent'] is True:
76+
self.parent_account = account
77+
self.parent_account_id = account_id
78+
if "saml_provider" in self.config['accounts'][account]:
79+
self.saml_provider = \
80+
self.config['accounts'][account]["saml_provider"]
81+
if saml_hub_spoke is True:
82+
if self.parent_account == "":
83+
raise Exception(
84+
"No account is marked as parent in the configuration file. "
85+
"One account should have parent: true"
86+
)
87+
7988
# Converts between friendly names and ids for accounts.
8089
def map_account(self, account):
8190
# If our account is numeric
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
global:
2+
names:
3+
policies: False
4+
roles: True
5+
users: True
6+
groups: True
7+
template_outputs: enabled
8+
saml_direct: True
9+
10+
accounts:
11+
payer:
12+
id: 727974079150
13+
saml_provider: OktaIDP
14+
dev01:
15+
id: 755535531790
16+
saml_provider: OktaIDP
17+
18+
roles:
19+
OpsStandard:
20+
trusts:
21+
- OktaIDP
22+
managed_policies:
23+
- arn:aws:iam::aws:policy/ReadOnlyAccess
24+
in_accounts:
25+
- all
26+
OpsAdmin:
27+
trusts:
28+
- OktaIDP
29+
managed_policies:
30+
- arn:aws:iam::aws:policy/AdministratorAccess
31+
in_accounts:
32+
- dev01
33+
OpsOrgAdmin:
34+
trusts:
35+
- OktaIDP
36+
managed_policies:
37+
- arn:aws:iam::aws:policy/AdministratorAccess
38+
in_accounts:
39+
- payer

0 commit comments

Comments
 (0)