UNPKG

5.87 kBJavaScriptView Raw
1'use strict';
2
3const Ram = require('@alicloud/ram');
4const getProfile = require('./profile').getProfile;
5const promiseRetry = require('./retry');
6const { red } = require('colors');
7const debug = require('debug')('fun:ram');
8
9const getRamClient = async () => {
10 const profile = await getProfile();
11
12 return new Ram({
13 accessKeyId: profile.accessKeyId,
14 accessKeySecret: profile.accessKeySecret,
15 endpoint: 'https://ram.aliyuncs.com',
16 opts: {
17 timeout: profile.timeout * 1000
18 }
19 });
20};
21
22function normalizeRoleOrPoliceName(roleName) {
23 return roleName.replace(/_/g, '-');
24}
25
26async function deletePolicyNotDefaultVersion(ram, policyName) {
27 const listResponse = await ram.listPolicyVersions({
28 PolicyType: 'Custom',
29 PolicyName: policyName
30 });
31
32 const versions = (listResponse.PolicyVersions || {}).PolicyVersion;
33 if (versions) {
34 for (let version of versions) {
35 if (version.IsDefaultVersion === false) {
36 await ram.deletePolicyVersion({
37 PolicyName: policyName,
38 VersionId: version.VersionId
39 });
40 }
41 }
42 }
43}
44
45async function makePolicy(policyName, policyDocument) {
46 const ram = await getRamClient();
47
48 let exists = true;
49
50 await promiseRetry(async (retry, times) => {
51 try {
52 try {
53 await ram.getPolicy({
54 PolicyType: 'Custom',
55 PolicyName: policyName
56 });
57 } catch (ex) {
58 if (ex.code !== 'EntityNotExist.Policy') {
59 throw ex;
60 } else { exists = false; }
61 }
62
63 if (!exists) {
64 await ram.createPolicy({
65 PolicyName: policyName,
66 Description: 'generated by fc fun',
67 PolicyDocument: JSON.stringify(policyDocument)
68 });
69 } else {
70 // avoid limitExceeded.Policy.Version
71 await deletePolicyNotDefaultVersion(ram, policyName);
72
73 await ram.createPolicyVersion({
74 PolicyName: policyName,
75 PolicyDocument: JSON.stringify(policyDocument),
76 SetAsDefault: true
77 });
78 }
79 } catch (ex) {
80 console.log(red(`retry ${times} times`));
81 retry(ex);
82 }
83 });
84}
85
86async function attachPolicyToRole(policyName, roleName, policyType = 'System') {
87 const ram = await getRamClient();
88
89 await promiseRetry(async (retry, times) => {
90 try {
91 const policies = await ram.listPoliciesForRole({
92 RoleName: roleName
93 });
94
95 var policy = policies.Policies.Policy.find((item) => {
96 return item.PolicyName === policyName;
97 });
98
99 if (!policy) {
100 await ram.attachPolicyToRole({
101 PolicyType: policyType,
102 PolicyName: policyName,
103 RoleName: roleName
104 });
105 }
106 } catch (ex) {
107 debug('error when attachPolicyToRole: %s, policyName %s, error is: \n%O', roleName, policyName, ex);
108
109 console.log(red(`retry ${times} times`));
110 retry(ex);
111 }
112 });
113}
114
115async function getRamRole(ramClient, roleName) {
116 try {
117 return await ramClient.getRole({
118 RoleName: roleName
119 });
120 } catch (ex) {
121 debug('error when getRole: %s, error is: \n%O', roleName, ex);
122 if (ex.name !== 'EntityNotExist.RoleError') {
123 throw ex;
124 }
125 }
126}
127
128async function makeRole(roleName, createRoleIfNotExist, description = 'FunctionCompute Default Role', assumeRolePolicy) {
129
130 const ram = await getRamClient();
131 var role;
132 await promiseRetry(async (retry, times) => {
133 try {
134 role = await getRamRole(ram, roleName);
135
136 if (!assumeRolePolicy) {
137 assumeRolePolicy = {
138 'Statement': [
139 {
140 'Action': 'sts:AssumeRole',
141 'Effect': 'Allow',
142 'Principal': {
143 'Service': [
144 'fc.aliyuncs.com'
145 ]
146 }
147 }
148 ],
149 'Version': '1'
150 };
151 }
152
153 if (!role && createRoleIfNotExist) {
154 role = await ram.createRole({
155 RoleName: roleName,
156 Description: description,
157 AssumeRolePolicyDocument: JSON.stringify(assumeRolePolicy)
158 });
159 } else if (!role) {
160 throw new Error(`role ${roleName} not exist`);
161 }
162 } catch (ex) {
163 debug('error when makeRole: %s, error is: \n%O', roleName, ex);
164
165 if (ex.code && ex.code.startsWith('InvalidParameter')) {
166 throw ex;
167 } else if (ex.code && ex.code === 'NoPermission') {
168 console.error(red(`\n${ex.message}\n\nMaybe you need grant AliyunRAMFullAccess policy to the sub-account or use the primary account. You can refer to Chinese doc https://github.com/aliyun/fun/blob/master/docs/usage/faq-zh.md#nopermissionerror-you-are-not-authorized-to-do-this-action-resource-acsramxxxxxxxxxxrole-action-ramgetrole or English doc https://github.com/aliyun/fun/blob/master/docs/usage/faq.md#nopermissionerror-you-are-not-authorized-to-do-this-action-resource-acsramxxxxxxxxxxrole-action-ramgetrole for help.\n\n` +
169 `If you don’t want use the AliyunRAMFullAccess policy or primary account, you can also specify the Role property for Service. You can refer to Chinease doc https://github.com/aliyun/fun/blob/master/docs/specs/2018-04-03-zh-cn.md#aliyunserverlessservice or Enaglish doc https://github.com/aliyun/fun/blob/master/docs/specs/2018-04-03.md#aliyunserverlessservice for help.\n`));
170
171 throw ex;
172 } else {
173 console.log(red(`retry ${times} times`));
174 retry(ex);
175 }
176 }
177 });
178
179 return role;
180}
181
182async function makeAndAttachPolicy(policyName, policyDocument, roleName) {
183 debug('begin makePolicy');
184 await makePolicy(policyName, policyDocument);
185 debug('begin attachPolicyToRole');
186 await attachPolicyToRole(policyName, roleName, 'Custom');
187}
188
189module.exports = {
190 makeRole, makePolicy,
191 attachPolicyToRole, makeAndAttachPolicy,
192 normalizeRoleOrPoliceName
193};
\No newline at end of file