Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SAAS-20313/Front-Door-https-only #1738

Merged
4 changes: 3 additions & 1 deletion exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,9 @@ module.exports = {
'eventHubMinimumTLSversion' : require(__dirname + '/plugins/azure/eventhub/eventHubMinimumTLSversion.js'),

'accessLogsEnabled' : require(__dirname + '/plugins/azure/frontdoor/accessLogsEnabled.js'),
'frontDoorMinimumTlsVersion' : require(__dirname + '/plugins/azure/frontdoor/frontDoorMinimumTlsVersion.js')
'frontDoorMinimumTlsVersion' : require(__dirname + '/plugins/azure/frontdoor/frontDoorMinimumTlsVersion.js'),
'frontDoorHttpsOnly' : require(__dirname + '/plugins/azure/frontdoor/frontDoorHttpsOnly.js'),

},
github: {
'publicKeysRotated' : require(__dirname + '/plugins/github/users/publicKeysRotated.js'),
Expand Down
5 changes: 5 additions & 0 deletions helpers/azure/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,11 @@ var calls = {
url: 'https://graph.microsoft.com/v1.0/servicePrincipals',
graph: true
}
},
classicFrontDoors: {
list: {
url: 'https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Network/frontDoors?api-version=2019-05-01'
}
}
};

Expand Down
3 changes: 2 additions & 1 deletion helpers/azure/locations.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,6 @@ module.exports = {
bastionHosts: locations,
applications: ['global'],
eventGrid: locations,
eventHub: locations
eventHub: locations,
classicFrontDoors: ['global'],
};
66 changes: 66 additions & 0 deletions plugins/azure/frontdoor/frontDoorHttpsOnly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const async = require('async');
const helpers = require('../../../helpers/azure');

module.exports = {
title: 'Front Door HTTPS only',
category: 'Front Door',
domain: 'Content Delivery',
description: 'Ensures HTTPS Only is enabled for Front Door Classic profile, redirecting all HTTP traffic to HTTPS.',
alphadev4 marked this conversation as resolved.
Show resolved Hide resolved
more_info: 'By using the HTTPS only protocol, you ensure that your sensitive data is delivered securely via TLS/SSL encryption.',
recommended_action: 'Ensure that Front Door (classic) under the frontend hosts section has HTTP to HTTPS redirect rule.',
alphadev4 marked this conversation as resolved.
Show resolved Hide resolved
link: 'https://learn.microsoft.com/en-us/azure/frontdoor/front-door-how-to-redirect-https',
apis: ['classicFrontDoors:list'],

run: function(cache, settings, callback) {
const results = [];
const source = {};
const locations = helpers.locations(settings.govcloud);
async.each(locations.classicFrontDoors, (location, rcb) => {
const classicFrontDoors =
helpers.addSource(cache, source,
['classicFrontDoors', 'list', location]);

if (!classicFrontDoors) return rcb();

if (classicFrontDoors.err || !classicFrontDoors.data) {
helpers.addResult(results, 3,
'Unable to query Front Door profiles: ' + helpers.addError(classicFrontDoors), location);
return rcb();
}

if (!classicFrontDoors.data.length) {
helpers.addResult(results, 0, 'No existing Front Door profiles found', location);
return rcb();
}

classicFrontDoors.data.forEach(function(frontDoor) {
mehakseedat63 marked this conversation as resolved.
Show resolved Hide resolved
if (!frontDoor.id || !frontDoor.routingRules) return;

var ruleFound = false;
for (var rule of frontDoor.routingRules) {
var ruleProperties = rule.properties? rule.properties : {};
if (ruleProperties.acceptedProtocols && ruleProperties.acceptedProtocols[0].toLowerCase() =='http') {
if (ruleProperties.routeConfiguration &&
ruleProperties.routeConfiguration.redirectType &&
ruleProperties.routeConfiguration.redirectProtocol &&
ruleProperties.routeConfiguration.redirectType.toLowerCase() == 'moved' &&
ruleProperties.routeConfiguration.redirectProtocol.toLowerCase() == 'httpsonly') {
ruleFound = true;
break;
}
}
}

if (ruleFound) {
helpers.addResult(results, 0, 'Front Door profile is configured to use HTTPS only', location, frontDoor.id);
} else {
helpers.addResult(results, 2, 'Front Door profile is not configured to use HTTPS only', location, frontDoor.id);
}

});
rcb();
}, function() {
callback(null, results, source);
});
}
};
128 changes: 128 additions & 0 deletions plugins/azure/frontdoor/frontDoorHttpsOnly.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
var expect = require('chai').expect;
var frontDoorHttpsOnly = require('./frontDoorHttpsOnly.js');

const classicFrontDoors = [
{
id: '/subscriptions/1234567890/resourcegroups/meerab-rg/providers/Microsoft.Network/frontdoors/aquatest',
type: 'Microsoft.Network/frontdoors',
name: 'aquatest',
location: 'Global',
tags: {},
routingRules: [
{
"id": "/subscriptions/1234567890/resourcegroups/meerab-rg/providers/Microsoft.Network/Frontdoors/aquatest/RoutingRules/test-instance",
"name": "test-instance",
"type": "Microsoft.Network/Frontdoors/RoutingRules",
"properties": {
"routeConfiguration": {
"redirectType": "Moved",
"redirectProtocol": "HttpsOnly",
},
"resourceState": "Enabled",
"acceptedProtocols": [
"Http"
]
}
},
{
"id": "/subscriptions/1234567890/resourcegroups/meerab-rg/providers/Microsoft.Network/Frontdoors/aquatest/RoutingRules/rule2",
"name": "rule2",
"type": "Microsoft.Network/Frontdoors/RoutingRules",
"properties": {
"routeConfiguration": {
"redirectType": "Found",
"redirectProtocol": "HttpOnly",
},
"acceptedProtocols": [
"Https"
],
}
}
]
},
{
id: '/subscriptions/1234567890/resourcegroups/meerab-rg/providers/Microsoft.Network/frontdoors/aquatest',
type: 'Microsoft.Network/frontdoors',
name: 'aquatest',
location: 'Global',
tags: {},
routingRules: [
{
"id": "/subscriptions/1234567890/resourcegroups/meerab-rg/providers/Microsoft.Network/Frontdoors/aquatest/RoutingRules/rule2",
"name": "rule2",
"type": "Microsoft.Network/Frontdoors/RoutingRules",
"properties": {
"routeConfiguration": {
"redirectType": "Found",
"redirectProtocol": "HttpOnly",
},
"acceptedProtocols": [
"Https"
],
}
}
]
}
];

const createCache = (classicFrontDoors) => {
return {
classicFrontDoors: {
list: {
'global': {
data: classicFrontDoors
}
}
}
};
};

const createErrorCache = () => {
return {
classicFrontDoors: {
list: {
'global': {
data:{}
}
}
}
};
};
describe('frontDoorHttpsOnly', function () {
describe('run', function () {

it('should give pass result if no classic Front Door profiles found', function (done) {
const cache = createErrorCache();
frontDoorHttpsOnly.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('No existing Front Door profiles found');
expect(results[0].region).to.equal('global');
done();
});
});

it('should give pass result if classic Front Door profile is configured to use Https only', function (done) {
const cache = createCache([classicFrontDoors[0]]);
frontDoorHttpsOnly.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(0);
expect(results[0].message).to.include('Front Door profile is configured to use HTTPS only');
expect(results[0].region).to.equal('global');
done();
});
});

it('should give fail result if classic Front Door profile is not configured to use Https only', function (done) {
const cache = createCache([classicFrontDoors[1]]);
frontDoorHttpsOnly.run(cache, {}, (err, results) => {
expect(results.length).to.equal(1);
expect(results[0].status).to.equal(2);
expect(results[0].message).to.include('Front Door profile is not configured to use HTTPS only');
expect(results[0].region).to.equal('global');
done();
});
});

});
});
Loading