1 | 'use strict';
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | return new (P || (P = Promise))(function (resolve, reject) {
|
4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
7 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8 | });
|
9 | };
|
10 | const Ram = require('@alicloud/ram');
|
11 | const getProfile = require('./profile').getProfile;
|
12 | const promiseRetry = require('./retry');
|
13 | const { red } = require('colors');
|
14 | const debug = require('debug')('fun:ram');
|
15 | const _ = require('lodash');
|
16 | const { throwProcessedPopPermissionError } = require('./error-message');
|
17 | const FNF_ASSUME_ROLE_POLICY = {
|
18 | 'Statement': [
|
19 | {
|
20 | 'Action': 'sts:AssumeRole',
|
21 | 'Effect': 'Allow',
|
22 | 'Principal': {
|
23 | 'Service': [
|
24 | 'fnf.aliyuncs.com'
|
25 | ]
|
26 | }
|
27 | }
|
28 | ],
|
29 | 'Version': '1'
|
30 | };
|
31 | const getRamClient = () => __awaiter(this, void 0, void 0, function* () {
|
32 | const profile = yield getProfile();
|
33 | const ram = new Ram({
|
34 | accessKeyId: profile.accessKeyId,
|
35 | accessKeySecret: profile.accessKeySecret,
|
36 | endpoint: 'https://ram.aliyuncs.com',
|
37 | opts: {
|
38 | timeout: profile.timeout * 1000
|
39 | }
|
40 | });
|
41 | const realRequest = ram.request.bind(ram);
|
42 | ram.request = (action, params, options) => __awaiter(this, void 0, void 0, function* () {
|
43 | try {
|
44 | return yield realRequest(action, params, options);
|
45 | }
|
46 | catch (ex) {
|
47 | yield throwProcessedPopPermissionError(ex, action);
|
48 | throw ex;
|
49 | }
|
50 | });
|
51 | return ram;
|
52 | });
|
53 | function normalizeRoleOrPoliceName(roleName) {
|
54 | return roleName.replace(/_/g, '-');
|
55 | }
|
56 | function deletePolicyNotDefaultVersion(ram, policyName) {
|
57 | return __awaiter(this, void 0, void 0, function* () {
|
58 | const listResponse = yield ram.listPolicyVersions({
|
59 | PolicyType: 'Custom',
|
60 | PolicyName: policyName
|
61 | });
|
62 | const versions = (listResponse.PolicyVersions || {}).PolicyVersion;
|
63 | if (versions) {
|
64 | for (let version of versions) {
|
65 | if (version.IsDefaultVersion === false) {
|
66 | yield ram.deletePolicyVersion({
|
67 | PolicyName: policyName,
|
68 | VersionId: version.VersionId
|
69 | });
|
70 | }
|
71 | }
|
72 | }
|
73 | });
|
74 | }
|
75 | function makePolicy(policyName, policyDocument) {
|
76 | return __awaiter(this, void 0, void 0, function* () {
|
77 | const ram = yield getRamClient();
|
78 | let exists = true;
|
79 | yield promiseRetry((retry, times) => __awaiter(this, void 0, void 0, function* () {
|
80 | try {
|
81 | try {
|
82 | yield ram.getPolicy({
|
83 | PolicyType: 'Custom',
|
84 | PolicyName: policyName
|
85 | });
|
86 | }
|
87 | catch (ex) {
|
88 | if (ex.code !== 'EntityNotExist.Policy') {
|
89 | throw ex;
|
90 | }
|
91 | else {
|
92 | exists = false;
|
93 | }
|
94 | }
|
95 | if (!exists) {
|
96 | yield ram.createPolicy({
|
97 | PolicyName: policyName,
|
98 | Description: 'generated by fc fun',
|
99 | PolicyDocument: JSON.stringify(policyDocument)
|
100 | });
|
101 | }
|
102 | else {
|
103 |
|
104 | yield deletePolicyNotDefaultVersion(ram, policyName);
|
105 | yield ram.createPolicyVersion({
|
106 | PolicyName: policyName,
|
107 | PolicyDocument: JSON.stringify(policyDocument),
|
108 | SetAsDefault: true
|
109 | });
|
110 | }
|
111 | }
|
112 | catch (ex) {
|
113 | if (ex.code && ex.code === 'NoPermission') {
|
114 | throw ex;
|
115 | }
|
116 | console.log(red(`retry ${times} times`));
|
117 | retry(ex);
|
118 | }
|
119 | }));
|
120 | });
|
121 | }
|
122 | function attachPolicyToRole(policyName, roleName, policyType = 'System') {
|
123 | return __awaiter(this, void 0, void 0, function* () {
|
124 | const ram = yield getRamClient();
|
125 | yield promiseRetry((retry, times) => __awaiter(this, void 0, void 0, function* () {
|
126 | try {
|
127 | const policies = yield ram.listPoliciesForRole({
|
128 | RoleName: roleName
|
129 | });
|
130 | var policy = policies.Policies.Policy.find((item) => {
|
131 | return _.toLower(item.PolicyName) === _.toLower(policyName);
|
132 | });
|
133 | if (!policy) {
|
134 | yield ram.attachPolicyToRole({
|
135 | PolicyType: policyType,
|
136 | PolicyName: policyName,
|
137 | RoleName: roleName
|
138 | });
|
139 | }
|
140 | }
|
141 | catch (ex) {
|
142 | if (ex.code && ex.code === 'NoPermission') {
|
143 | throw ex;
|
144 | }
|
145 | debug('error when attachPolicyToRole: %s, policyName %s, error is: \n%O', roleName, policyName, ex);
|
146 | console.log(red(`retry ${times} times`));
|
147 | retry(ex);
|
148 | }
|
149 | }));
|
150 | });
|
151 | }
|
152 | function getRamRole(ramClient, roleName) {
|
153 | return __awaiter(this, void 0, void 0, function* () {
|
154 | try {
|
155 | return yield ramClient.getRole({
|
156 | RoleName: roleName
|
157 | });
|
158 | }
|
159 | catch (ex) {
|
160 | debug('error when getRole: %s, error is: \n%O', roleName, ex);
|
161 | if (ex.name !== 'EntityNotExist.RoleError') {
|
162 | throw ex;
|
163 | }
|
164 | }
|
165 | });
|
166 | }
|
167 | function makeRole(roleName, createRoleIfNotExist, description = 'FunctionCompute Default Role', assumeRolePolicy) {
|
168 | return __awaiter(this, void 0, void 0, function* () {
|
169 | const ram = yield getRamClient();
|
170 | var role;
|
171 | yield promiseRetry((retry, times) => __awaiter(this, void 0, void 0, function* () {
|
172 | try {
|
173 | role = yield getRamRole(ram, roleName);
|
174 | if (!assumeRolePolicy) {
|
175 | assumeRolePolicy = {
|
176 | 'Statement': [
|
177 | {
|
178 | 'Action': 'sts:AssumeRole',
|
179 | 'Effect': 'Allow',
|
180 | 'Principal': {
|
181 | 'Service': [
|
182 | 'fc.aliyuncs.com'
|
183 | ]
|
184 | }
|
185 | }
|
186 | ],
|
187 | 'Version': '1'
|
188 | };
|
189 | }
|
190 | if (!role && createRoleIfNotExist) {
|
191 | role = yield ram.createRole({
|
192 | RoleName: roleName,
|
193 | Description: description,
|
194 | AssumeRolePolicyDocument: JSON.stringify(assumeRolePolicy)
|
195 | });
|
196 | }
|
197 | else if (!role) {
|
198 | throw new Error(`role ${roleName} not exist`);
|
199 | }
|
200 | }
|
201 | catch (ex) {
|
202 | debug('error when makeRole: %s, error is: \n%O', roleName, ex);
|
203 | if (ex.code && ex.code.startsWith('InvalidParameter')) {
|
204 | throw ex;
|
205 | }
|
206 | else if (ex.code && ex.code === 'NoPermission') {
|
207 | throw ex;
|
208 | }
|
209 | else {
|
210 | console.log(red(`retry ${times} times`));
|
211 | retry(ex);
|
212 | }
|
213 | }
|
214 | }));
|
215 | return role;
|
216 | });
|
217 | }
|
218 | function makeAndAttachPolicy(policyName, policyDocument, roleName) {
|
219 | return __awaiter(this, void 0, void 0, function* () {
|
220 | debug('begin makePolicy');
|
221 | yield makePolicy(policyName, policyDocument);
|
222 | debug('begin attachPolicyToRole');
|
223 | yield attachPolicyToRole(policyName, roleName, 'Custom');
|
224 | });
|
225 | }
|
226 | module.exports = {
|
227 | makeRole, makePolicy,
|
228 | attachPolicyToRole, makeAndAttachPolicy,
|
229 | normalizeRoleOrPoliceName,
|
230 | FNF_ASSUME_ROLE_POLICY
|
231 | };
|