Skip to content

Commit 5eb677d

Browse files
author
kkuzmin
authored
Merge pull request #14 from alertlogic/msi
Managed Service Identity support.
2 parents 476bad4 + b5a5260 commit 5eb677d

File tree

3 files changed

+100
-19
lines changed

3 files changed

+100
-19
lines changed

master.js

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111

1212
const async = require('async');
1313

14-
const azureRest = require('ms-rest-azure');
15-
const azureArmClient = require('azure-arm-resource').ResourceManagementClient;
14+
const msRestAzure = require('ms-rest-azure');
1615
const azureArmWebsite = require('azure-arm-website');
1716
const fileTokenCache = require('azure/lib/util/fileTokenCache');
1817

@@ -108,25 +107,29 @@ class AlAzureMaster {
108107
this._alDataResidency = alDataResidency ? alDataResidency : process.env.CUSTOMCONNSTR_APP_AL_RESIDENCY;
109108

110109
// Init Azure optional configuration parameters
111-
this._clientId = clientId ? clientId : process.env.CUSTOMCONNSTR_APP_CLIENT_ID;
112110
this._domain = domain ? domain : process.env.APP_TENANT_ID;
113-
this._clientSecret = clientSecret ? clientSecret : process.env.CUSTOMCONNSTR_APP_CLIENT_SECRET;
111+
this._clientId = clientId ? clientId :
112+
process.env.MSI_SECRET ? process.env.APP_PRINCIPAL_ID : process.env.CUSTOMCONNSTR_APP_CLIENT_ID;
113+
this._clientSecret = clientSecret ? clientSecret :
114+
process.env.MSI_SECRET ? 'Managed Service Identity' : process.env.CUSTOMCONNSTR_APP_CLIENT_SECRET;
114115
this._subscriptionId = subscriptionId ? subscriptionId : process.env.APP_SUBSCRIPTION_ID;
115116
this._resourceGroup = resourceGroup ? resourceGroup : process.env.APP_RESOURCE_GROUP;
116117
this._webAppName = webAppName ? webAppName : process.env.WEBSITE_SITE_NAME;
117118

118119
// Init Azure SDK
119-
var tokenCache = new fileTokenCache(m_util.getADCacheFilename(
120-
'https://management.azure.com',
121-
this._clientId,
122-
this._domain));
123-
124-
this._azureCreds = new azureRest.ApplicationTokenCredentials(
125-
this._clientId,
126-
this._domain,
127-
this._clientSecret,
128-
{ 'tokenCache': tokenCache });
129-
120+
if (process.env.MSI_ENDPOINT && process.env.MSI_SECRET) {
121+
this._azureCreds = new msRestAzure.MSIAppServiceTokenCredentials();
122+
} else {
123+
const tokenCache = new fileTokenCache(m_util.getADCacheFilename(
124+
'https://management.azure.com',
125+
this._clientId,
126+
this._domain));
127+
this._azureCreds = new msRestAzure.ApplicationTokenCredentials(
128+
this._clientId,
129+
this._domain,
130+
this._clientSecret,
131+
{ 'tokenCache': tokenCache });
132+
}
130133
this._azureWebsiteClient = new azureArmWebsite(this._azureCreds, this._subscriptionId);
131134
this._appStats = new AzureWebAppStats(collectorAzureFunNames);
132135
this._collectionStats = new AzureCollectionStats(azureContext, {outputQueueBinding: OutputStatsBinding});

test/master_test.js

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ describe('Master tests', function() {
172172
aimsKeyId: 'aimsKeyId',
173173
aimsKeySecret: 'aimsKeySecret',
174174
alApiEndpoint: 'alApiEndpoint',
175-
alIngestEndpoint: 'alIngestEndpoint',
175+
alAzcollectEndpoint: 'alAzcollectEndpoint',
176176
alDataResidency: 'default'
177177
};
178178
var azureOpts = {
@@ -197,7 +197,77 @@ describe('Master tests', function() {
197197
done();
198198
});
199199
});
200-
200+
201+
it('Verify register with MSI', function(done) {
202+
// Mock Azure HTTP calls
203+
nock('http://127.0.0.1:41963', {'encodedQueryParams':true})
204+
.get(/token\/$/, /.*/ )
205+
.query(true)
206+
.times(5)
207+
.reply(200, mock.AZURE_TOKEN_MOCK);
208+
209+
nock('https://management.azure.com:443', {'encodedQueryParams':true})
210+
.put(/appsettings/, /.*/ )
211+
.query(true)
212+
.times(4)
213+
.reply(200, {});
214+
215+
nock('https://management.azure.com:443', {'encodedQueryParams':true})
216+
.post(/appsettings/, /.*/ )
217+
.query(true)
218+
.times(4)
219+
.reply(200, {});
220+
221+
// Mock Alert Logic HTTP calls
222+
fakePost = sinon.stub(alcollector.AlServiceC.prototype, 'post');
223+
fakePost.withArgs('/azure/ehub/subscription-id/rg/app-name')
224+
.resolves({
225+
source: {
226+
host: {
227+
id: 'new-host-id1'
228+
},
229+
id: 'new-source-id1'
230+
}
231+
});
232+
233+
var alOpts = {
234+
aimsKeyId: 'aimsKeyId',
235+
aimsKeySecret: 'aimsKeySecret',
236+
alApiEndpoint: 'alApiEndpoint',
237+
alDataResidency: 'default'
238+
};
239+
240+
delete process.env.COLLECTOR_HOST_ID;
241+
delete process.env.COLLECTOR_SOURCE_ID;
242+
process.env.WEBSITE_SITE_NAME = 'app-name';
243+
process.env.APP_SUBSCRIPTION_ID = 'subscription-id';
244+
process.env.APP_RESOURCE_GROUP = 'rg';
245+
process.env.MSI_SECRET = 'MSI secret';
246+
process.env.MSI_ENDPOINT = 'http://127.0.0.1:41963/MSI/token/';
247+
process.env.APP_PRINCIPAL_ID = 'msi-principal-id';
248+
249+
var master = new AlAzureMaster(mock.DEFAULT_FUNCTION_CONTEXT, 'ehub', '1.0.0', [], [], alOpts);
250+
251+
master.register({}, function(err, collectorHostId, collectorSourceId){
252+
if (err) console.log(err);
253+
assert.equal(collectorHostId, 'new-host-id1');
254+
assert.equal(collectorSourceId, 'new-source-id1');
255+
const expectedBody = {
256+
body: {
257+
app_tenant_id: 'tenant-id',
258+
client_id: process.env.APP_PRINCIPAL_ID,
259+
client_secret: 'Managed Service Identity',
260+
version: '1.0.0'
261+
}
262+
};
263+
sinon.assert.calledWith(fakePost, '/azure/ehub/subscription-id/rg/app-name', expectedBody);
264+
delete process.env.MSI_SECRET;
265+
delete process.env.MSI_ENDPOINT;
266+
delete process.env.APP_PRINCIPAL_ID;
267+
done();
268+
});
269+
});
270+
201271
it('Verify register reuse endpoints and collector ids from env', function(done) {
202272
// Expected Alert Logic parameters
203273
process.env.WEBSITE_HOSTNAME = 'app-name';

updater.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,17 @@ class AlAzureUpdater {
3636
this._webAppName = webAppName ? webAppName : process.env.WEBSITE_SITE_NAME;
3737
}
3838

39+
_getAzureCredentials() {
40+
if (process.env.MSI_ENDPOINT && process.env.MSI_SECRET) {
41+
return new msRestAzure.MSIAppServiceTokenCredentials();
42+
} else {
43+
return new msRestAzure.ApplicationTokenCredentials(this._clientId, this._domain, this._clientSecret);
44+
}
45+
}
46+
3947
syncWebApp(callback) {
40-
var credentials = new msRestAzure.ApplicationTokenCredentials(this._clientId, this._domain, this._clientSecret);
41-
var webSiteClient = new WebSiteManagement(credentials, this._subscriptionId);
48+
const credentials = this._getAzureCredentials();
49+
const webSiteClient = new WebSiteManagement(credentials, this._subscriptionId);
4250
return webSiteClient.webApps.syncRepository(this._resourceGroup, this._webAppName, callback);
4351
}
4452
};

0 commit comments

Comments
 (0)