Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Document Content for Article("Sharing service catalog portfolios to different accounts under the organization unit")
{
"OU_ID": "<*********************>",
"PortID": "<*********************>",
"DestinationAccountIDs": ["customeraccount1","customeraccount2","customeraccount3"]
}
##IAM policy to attach to “Servicecatalogcrossaccount“(cross-account role)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"servicecatalog:AssociatePrincipalWithPortfolio",
"servicecatalog:CreatePortfolioShare",
"iam:GetUser",
"servicecatalog:AcceptPortfolioShare"
],
"Resource": "*"
}
]
}
##IAM policy that needs to the IAM role for lambda function
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::servicecatalogclientinfo/client.json"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:GetPolicyVersion",
"iam:ListRoleTags",
"iam:GetPolicy",
"iam:TagRole",
"iam:DeletePolicyVersion",
"iam:ListPolicyVersions",
"iam:UpdateRole",
"iam:CreatePolicyVersion",
"iam:GetRolePolicy"
],
"Resource": [
"arn:aws:iam::*:policy/*",
"arn:aws:iam::*:user/*",
"arn:aws:iam::*:role/*"
]
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": "logs:PutLogEvents",
"Resource": "arn:aws:logs:*:*:log-group:*:log-stream:*"
},
{
"Sid": "VisualEditor3",
"Effect": "Allow",
"Action": "logs:CreateLogStream",
"Resource": "arn:aws:logs:*:*:log-group:*"
},
{
"Sid": "VisualEditor4",
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "*"
},
{
"Sid": "VisualEditor6",
"Effect": "Allow",
"Action": [
"organizations:ListRoots",
"organizations:UntagResource",
"organizations:DescribeAccount",
"servicecatalog:CreatePortfolioShare",
"organizations:CreateAccount",
"organizations:DeleteOrganization",
"organizations:DescribePolicy",
"organizations:ListChildren",
"organizations:TagResource",
"organizations:EnableAWSServiceAccess",
"organizations:ListCreateAccountStatus",
"organizations:DescribeOrganization",
"organizations:CreateGovCloudAccount",
"organizations:EnableAllFeatures",
"organizations:DescribeOrganizationalUnit",
"organizations:DescribeHandshake",
"organizations:CreatePolicy",
"organizations:DescribeCreateAccountStatus",
"organizations:CreateOrganization",
"organizations:ListPoliciesForTarget",
"organizations:ListTagsForResource",
"organizations:ListTargetsForPolicy",
"organizations:DisableAWSServiceAccess",
"organizations:ListAWSServiceAccessForOrganization",
"organizations:ListPolicies",
"organizations:ListHandshakesForOrganization",
"organizations:ListAccountsForParent",
"organizations:LeaveOrganization",
"organizations:ListHandshakesForAccount",
"organizations:ListAccounts",
"organizations:ListParents",
"organizations:ListOrganizationalUnitsForParent"
],
"Resource": "*"
} ]
}
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": [
"arn:aws:iam::<customeraccountID>:role/Servicecatalogcrossaccount"
]
}
import json
import boto3
import os
import time
def get_account_id(context):
return context.invoked_function_arn.split(':')[3]
def lambda_handler(event, context):
####################### ENVIRONMENT VARIABLES ################################
s3_obj =boto3.client('s3')
s3_clientobj = s3_obj.get_object(Bucket='servicecatalogclientinfo', Key='client.json')
s3_clientdata = s3_clientobj['Body'].read().decode('utf-8')
clientdata = json.loads(s3_clientdata)
Destination_AccountIDs = clientdata['DestinationAccountIDs']
ORGANIZATIONALUNIT_ID = clientdata['OU_ID']
Port_ID = clientdata['PortID']
###############################################################################
sts_connection = boto3.client('sts')
servicecatalog = boto3.client('servicecatalog')
iam = boto3.resource('iam')
iamclient = boto3.client('iam')
share_catalog_product = servicecatalog.create_portfolio_share(
AcceptLanguage='en',
PortfolioId=Port_ID,
OrganizationNode={
'Type': 'ORGANIZATIONAL_UNIT',
'Value': ORGANIZATIONALUNIT_ID
}
)
test=[]
for accountID in Destination_AccountIDs:
arn = 'arn:aws:iam::'+accountID+':role/Servicecatalogcrossaccount'
policy = iam.Policy('arn:aws:iam::518164082586:policy/Assumerole-policy')
version = policy.default_version
policyJson = version.document
test.append(arn)
policyJson['Statement'][0]['Resource'].extend(test)
policyJson['Statement'][0]['Resource']=list(dict.fromkeys(policyJson['Statement'][0]['Resource']))
print(policyJson)
policylatestversion = iamclient.create_policy_version(
PolicyArn= 'arn:aws:iam::518164082586:policy/Assumerole-policy',
PolicyDocument= json.dumps(policyJson),
SetAsDefault= True
)
print(policylatestversion)
delete_older_version = iamclient.delete_policy_version(
PolicyArn= 'arn:aws:iam::518164082586:policy/Assumerole-policy',
VersionId= version.version_id
)
time.sleep(30)
for accountID in Destination_AccountIDs:
acct_b = sts_connection.assume_role(
RoleArn="arn:aws:iam::"+accountID+":role/Servicecatalogcrossaccount",
RoleSessionName="cross_acct_lambda"
)
ACCESS_KEY = acct_b['Credentials']['AccessKeyId']
SECRET_KEY = acct_b['Credentials']['SecretAccessKey']
SESSION_TOKEN = acct_b['Credentials']['SessionToken']
dest_account=boto3.client('servicecatalog',region_name=get_account_id(context),aws_access_key_id=ACCESS_KEY,aws_secret_access_key=SECRET_KEY,aws_session_token=SESSION_TOKEN)
add_IAM_user = dest_account.associate_principal_with_portfolio(
AcceptLanguage='en',
PortfolioId=Port_ID,
PrincipalARN="arn:aws:iam::"+accountID+":user/CatalogUser",
PrincipalType='IAM'
)
print("Portfolio shared with reference "+share_catalog_product['PortfolioShareToken'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment