UNPKG

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